web-dev-qa-db-ja.com

RecyclerView.getChild(index)は、リストがスクロールされるとnullを表示します(インデックスがめちゃくちゃになります)

私は自分のAndroidアプリケーションでSwipeableRecyclerViewを使用して、recyclerViewのスワイプを有効にしています。RecyclerViewにはcardViewのリストが含まれています。

左にスワイプすると削除されるカードの元に戻す機能を実装しようとしていました(最初のスワイプで元に戻し、次のスワイプで削除がトリガーされます)

私は次のコードを試しています(一部機能していると思います)

SwipeableRecyclerViewTouchListener srvTouchListner = new SwipeableRecyclerViewTouchListener(rvTimerList,
            new SwipeableRecyclerViewTouchListener.SwipeListener(){

                @Override
                public boolean canSwipe(int i) {
                    return true;
                }

                @Override
                public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] ints) {
                    for(int position : ints){
                        View view = recyclerView.getChildAt(position);
                            if (view.getTag(R.string.card_undo) == null) {
                                if(viewStack == null) {
                                    saveToViewStack(position, view);
                                    final ViewGroup viewGroup = (ViewGroup) view.findViewById(R.id.time_card2);
                                    view.setTag(R.string.card_undo, "true");
                                    viewGroup.addView(view.inflate(TimerSummary.this, R.layout.timeslot_card_undo, null));
                                }
                            } else {
                                Log.d(TAG, "Removing Item");
                                deleteTimeSlot(timerInstanceList.get(position));
                                Toast.makeText(TimerSummary.this, "Deleted!", Toast.LENGTH_SHORT).show();
                                timerInstanceList.remove(position);
                                finalSummaryAdapter.notifyItemRemoved(position);
                            }

                    }
                    finalSummaryAdapter.notifyDataSetChanged();
                }
                @Override
                public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] ints) {
                    for (int position:ints){
                        View view = recyclerView.getChildAt(position);
                        if(view.getTag(R.string.card_undo) != null && view.getTag(R.string.card_undo).equals("true")){
                            viewStack = null;
                            recyclerView.setAdapter(finalSummaryAdapter);
                        }
                    }

                }
            });

アイテムが多い場合(スクロールが必要)

View view = recyclerView.getChildAt(position);

アプリのクラッシュを引き起こすnull参照を返します。

見方を間違えているのではないかと思います。私はビューホルダーに関連するものを使用する必要がありますが、実際にはビューホルダーから必要なビューを取得する方法について少し混乱しています。

誰かが役立つ何かを共有できれば、それは素晴らしいことです!誰かがそれを望んでいるなら、私はもっと情報を提供させていただきます、

14
P-RAD

findViewHolderForAdapterPositionを使用する必要があります。 https://developer.Android.com/reference/Android/support/v7/widget/RecyclerView.html#findViewHolderForAdapterPosition(int)

位置がレイアウトされていない場合(範囲外または削除された場合など)はnullを返すことに注意してください。

21
yigit

@yigitの答えにコメントするのに十分な評判ポイントがないため、現在viewGroupにあるものに関係なく、RecyclerViewからすべてのviewHolderを取得する方法を提供すると思いました。 findViewHolderForAdapterPositionとForLayoutPositionを使用しても、RecyclerViewでViewHolderのnullインスタンスを取得できます。

これを回避するために、findViewHolderForItemId [1]を使用し、RecyclerView.Adapter#getItemId(int position)[を使用してアダプター内のviewHolderのIDを渡すことができます2]

for (int i = 0; i < mAdapter.getItemCount(); i++) {
    RecyclerView.ViewHolder holder = 
            mRecyclerView.findViewHolderForItemId(mAdapter.getItemId(i));
}
  1. https://developer.Android.com/reference/Android/support/v7/widget/RecyclerView.html#findViewHolderForItemId(int)
  2. https://developer.Android.com/reference/Android/support/v7/widget/RecyclerView.Adapter.html#getItemId(int)
9
Brandon McAnsh

RecyclerViewのLayoutManagerでfindFirstCompletelyVisibleItemPosition()およびfindLastVisibleItemPosition()メソッドを使用して、探している子が表示されているかどうかを確認します。表示されている場合は、getChild(index)を使用してその特定の子のViewHolderインスタンスを取得できます。それがnullでない場合はnullになる可能性があります(子がその中にない場合)。子が表示されていない場合は、特定の位置のListオブジェクトを変更するだけで、次に表示されるたびにUIが更新されます。

if (selectedPosition >= linearLayoutManager.findFirstVisibleItemPosition()
                    && selectedPosition <= linearLayoutManager.findLastVisibleItemPosition()){
                    linearLayoutManager.getChildAt(selectedPosition).setBackgroundResource(0);
                }
1