RecyclerView.getChild(index) shows null when list is scrolled (index gets messed up)

谁都会走 提交于 2020-01-10 13:30:31

问题


I've been using SwipeableRecyclerView for my android application for enabling swipes for my recyclerView. RecyclerView contains a list of cardViews.

I was trying to implement undo functionality for cards which will get deleted when swipe to left (first swipe shows undo, next swipe triggers delete)

I am trying the following code (partially working I guess)

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);
                        }
                    }

                }
            });

when Items are more (needs scrolling)

View view = recyclerView.getChildAt(position);

returns a null reference which causes an app crash.

I doubt that I am using the wrong method for taking view. I should be using something related with viewholder, I am actually kind of confused about how to get the view which you want from viewholder.

If anybody can share anything that helps,, that'll be great! I ll be happy to provide any more infos if somebody wants it,


回答1:


You should use findViewHolderForAdapterPosition. https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#findViewHolderForAdapterPosition(int)

Keep in mind that it will return null if the position is not laid out (e.g. out of bounds or removed).




回答2:


Since I don't have enough reputation points to comment on @yigit's answer, I thought I would give a way to retrieve all viewHolders from a RecyclerView regardless of what is currently in the viewGroup. Even with findViewHolderForAdapterPosition and ForLayoutPosition we still can get a null instance of the ViewHolder in the RecyclerView.

To circumvent this, we can use findViewHolderForItemId[1] and pass the ID of the viewHolder in the adapter using RecyclerView.Adapter#getItemId(int position)[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)



回答3:


Use findFirstCompletelyVisibleItemPosition() & findLastVisibleItemPosition() methods on LayoutManager of your RecyclerView to find out that the child you are looking for is visible or not. If it is visible then you can use getChild(index) to get the ViewHolder instance of that particular child and it wouldn't be null else it could be null(If the child is not in it). In case your child is not visible you just make changes in your specific position List object, next time whenever it'll be visible will have updated UI.

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


来源:https://stackoverflow.com/questions/30860843/recyclerview-getchildindex-shows-null-when-list-is-scrolled-index-gets-messed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!