質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

1329閲覧

RecyclerViewの非表示箇所をクリック時にNullPointエラー

FSNY

総合スコア16

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2018/05/13 06:55

RecyclerViewを使って1行で横方向にスクロールする画像のリストを作成しています。
そしてその各リストアイテムごとにOnClickのリスナーを付けて、クリックされた画像に選択されたことを示す枠を画像の背景として付けています。

リストのアイテム数が画面に表示できる数に収まっている場合は正常にクリックイベントを取得できて、
・既存の選択画像から枠を外す
・新しい選択画像に枠を付ける
という処理ができるのですが、
RecyclerViewには表示できる数しかアイテムが登録されておらず、表示できる数を超えていてリストをスクロール後にクリックすると存在しないViewを参照しようとしてNullPointエラーになってしまいます。
何か最初に一気にRecyclerViewにアイテムを登録する方法などあるのでしょうか?

下記
・RecyclerViewのAdapter
・RecyclerViewを利用するActivity
・RecyclerViewに登録するアイテム
それぞれのソースになります。

■RecyclerViewのAdapter

Android

1public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { 2 3 private LayoutInflater inflater; 4 private ArrayList<String> photoPathList; 5 private RecyclerViewClickListener recyclerViewClickListener; 6 7 public interface RecyclerViewClickListener{ 8 void onRecyclerViewClicked(View v, int position); 9 } 10 11 public RecyclerViewAdapter(Context context, ArrayList<String> pathList, RecyclerViewClickListener listener) { 12 inflater = LayoutInflater.from(context); 13 photoPathList = pathList; 14 recyclerViewClickListener = listener; 15 } 16 17 @Override 18 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 19 return new ViewHolder(inflater.inflate(R.layout.thumbnail_list_item, parent, false)); 20 } 21 22 @Override 23 public void onBindViewHolder(ViewHolder viewHolder, final int position) { 24 viewHolder.thumbnailImage.setImageResource(R.drawable.make_movie_no_choice); 25 viewHolder.thumbnailNo.setText(Integer.toString(position + 1)); 26 27 if(position == 0){ 28 viewHolder.thumbnailImage.setBackgroundResource(R.drawable.thumbnail_border); 29 } 30 31 viewHolder.itemView.setOnClickListener(new View.OnClickListener() { 32 @Override 33 public void onClick(View view) { 34 recyclerViewClickListener.onRecyclerViewClicked(view, position); 35 } 36 }); 37 } 38 39 @Override 40 public int getItemCount() { 41 if (photoPathList == null) { 42 return 0; 43 } 44 else { 45 return photoPathList.size(); 46 } 47 } 48 49 // ViewHolder 50 public class ViewHolder extends RecyclerView.ViewHolder { 51 FrameLayout thumbnailLayout; 52 ImageView thumbnailImage; 53 TextView thumbnailNo; 54 55 public ViewHolder(View itemView) { 56 super(itemView); 57 thumbnailLayout = (FrameLayout)itemView.findViewById(R.id.list_item_layout); 58 thumbnailImage = (ImageView)itemView.findViewById(R.id.list_item_thumbnail); 59 thumbnailNo = (TextView)itemView.findViewById(R.id.list_item_number); 60 } 61 } 62}

■RecyclerViewを利用するActivity

Android

1private RecyclerView recyclerView; 2private RecyclerView.Adapter adapter; 3private LinearLayoutManager layoutManager; 4private ArrayList<String> filePathList; 5 6protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.scene_confirm_photo_activity); 9 10 filePathList = intent.getStringArrayListExtra("addPhotoFilePathList"); 11 12 recyclerView = findViewById(R.id.scene_confirm_photo_thumbnail_list); 13 recyclerView.setHasFixedSize(true); 14 layoutManager = new LinearLayoutManager(this); 15 layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); 16 recyclerView.setLayoutManager(layoutManager); 17 adapter = new RecyclerViewAdapter(this, filePathList, this); 18 recyclerView.setAdapter(adapter); 19} 20 21@Override 22public void onRecyclerViewClicked(View v, int position) { 23 FrameLayout thumbnailLayout; 24 ImageView thumbnailImage; 25 26 for(int i = 0; i < filePathList.size(); i++){ 27 thumbnailLayout = (FrameLayout)recyclerView.getChildAt(i); 28 thumbnailImage = (ImageView)thumbnailLayout.getChildAt(0); 29 30 if(i == position){ 31 thumbnailImage.setBackgroundResource(R.drawable.thumbnail_border); 32 } 33 else{ 34 thumbnailImage.setBackgroundResource(0); 35 thumbnailImage.setPadding(0, 0, 0, 0); 36 } 37 } 38}

■RecyclerViewに登録するアイテム

Android

1<?xml version="1.0" encoding="utf-8"?> 2<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:id="@+id/list_item_layout" 4 android:layout_width="wrap_content" 5 android:layout_height="wrap_content" 6 android:gravity="center" 7 android:orientation="horizontal" 8 android:layout_margin="5dp"> 9 10 <ImageView 11 android:id="@+id/list_item_thumbnail" 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:adjustViewBounds="true"/> 15 16 <TextView 17 android:id="@+id/list_item_number" 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:layout_gravity="end|bottom" 21 android:text="1" 22 android:paddingTop="3dp" 23 android:paddingBottom="3dp" 24 android:paddingLeft="5dp" 25 android:paddingRight="5dp" 26 android:background="@color/colorBlack" 27 android:textColor="@color/colorWhite" /> 28 29</FrameLayout>

■エラーメッセージ
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.widget.FrameLayout.getChildAt(int)' on a null object reference

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

RecyclerViewではメモリ節約やパフォーマンス向上のために、範囲外に出た子Viewは画面から取り除かれ、次に新しい子Viewが必要になった時にリサイクルされ使いまわされます。(そもそもそれがRecyclerViewという名称の由来です。)

なので、getChildAtで子Viewを取得して何らかの操作をするというのはRecyclerViewでは使えません。アイテムクリック時に子Viewを自分でいじるのではなく、子Viewの状態を表すデータをAdapterに渡して、それをonBindViewHolder内で子Viewに反映するように考え方を切り替えてみてください。

ソースコードを拝見した感じでは、一つのアイテムを選択できるようにするのが目的のようなので、以下のような実装でいかがでしょうか。

java

1public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { 2 3 private LayoutInflater inflater; 4 private ArrayList<String> photoPathList; 5 private RecyclerViewClickListener recyclerViewClickListener; 6 7 // 選択されたアイテムの位置 8 private int selectedPosition = 0; 9 10 // 指定した位置のアイテムを選択状態にする 11 public void selectItemAt(int position) { 12 this.selectedPosition = position; 13 // 子Viewの状態が変わったことを通知し更新を促す 14 notifyDataSetChanged(); 15 } 16 17 ... 18 19 @Override 20 public void onBindViewHolder(ViewHolder viewHolder, final int position) { 21 viewHolder.thumbnailImage.setImageResource(R.drawable.make_movie_no_choice); 22 viewHolder.thumbnailNo.setText(Integer.toString(position + 1)); 23 24 // 選択されたアイテムなら背景を表示 25 if (position == selectedPosition){ 26 viewHolder.thumbnailImage.setBackgroundResource(R.drawable.thumbnail_border); 27 } else{ 28 viewHolder.thumbnailImage.setBackgroundResource(0); 29 viewHolder.thumbnailImage.setPadding(0, 0, 0, 0); 30 } 31 32 viewHolder.itemView.setOnClickListener(new View.OnClickListener() { 33 @Override 34 public void onClick(View view) { 35 recyclerViewClickListener.onRecyclerViewClicked(view, position); 36 } 37 }); 38 } 39} 40 41// in Activity 42@Override 43public void onRecyclerViewClicked(View v, int position) { 44 adapter.selectItemAt(position); 45}

投稿2018/05/13 18:19

kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FSNY

2018/05/14 01:20

ご教示いただいた修正案で思う形の動作を行うことができました! 大変助かりました、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問