No animation on item removal on RecyclerView

后端 未结 8 1071
故里飘歌
故里飘歌 2020-12-23 18:47

I am using RecyclerView for the first time. Everything is working fine except that there is no animation on item removal even though the animation on item addit

相关标签:
8条回答
  • 2020-12-23 19:31

    Solved it.

    The issue was that, after calling mAdapter.remove(position), another part of my code was calling mAdapter.notifyDataSetChanged() which I assume stops the removal animation.

    To sum up, if you call mAdapter.notifyDataSetChanged while there is an animation ongoing the animation will stop.

    0 讨论(0)
  • 2020-12-23 19:32

    Late but might be helpful to someone, who want {search items with animation}

    Use below code In your activity or fragment where

    yourAdapter.animateTo(filteredModelList);
    

    Use below code in your RecyclerAdapter class

    public void animateTo(List<CommonModel> models) {
            applyAndAnimateRemovals(models);
            applyAndAnimateAdditions(models);
            applyAndAnimateMovedItems(models);
        }
    
        private void applyAndAnimateRemovals(List<CommonModel> newModels) {
            for (int i = items.size() - 1; i >= 0; i--) {
                final CommonModel model = items.get(i);
                if (!newModels.contains(model)) {
                    removeItem(i);
                }
            }
        }
    
        private void applyAndAnimateAdditions(List<CommonModel> newModels) {
            for (int i = 0, count = newModels.size(); i < count; i++) {
                final CommonModel model = newModels.get(i);
                if (!items.contains(model)) {
                    addItem(i, model);
                }
            }
        }
    
        private void applyAndAnimateMovedItems(List<CommonModel> newModels) {
            for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
                final CommonModel model = newModels.get(toPosition);
                final int fromPosition = items.indexOf(model);
                if (fromPosition >= 0 && fromPosition != toPosition) {
                    moveItem(fromPosition, toPosition);
                }
            }
        }
    
        private CommonModel removeItem(int position) {
            final CommonModel model = items.remove(position);
            notifyItemRemoved(position);
            return model;
        }
    
        private void addItem(int position, CommonModel model) {
            items.add(position, model);
            notifyItemInserted(position);
        }
    
        private void moveItem(int fromPosition, int toPosition) {
            final CommonModel model = items.remove(fromPosition);
            items.add(toPosition, model);
            notifyItemMoved(fromPosition, toPosition);
        }
    
    0 讨论(0)
  • 2020-12-23 19:34

    Use notifyItemRemoved(position) instead of notifyDataSetChanged() like below

    myDataset.remove(position);
    notifyItemRemoved(position);
    

    because notifyDataSetChanged() simply notifies the updated data without any animations.

    0 讨论(0)
  • 2020-12-23 19:39

    after long debugging I realized I had to add setHasStableIds(true) to my adapter and implement

    @Override
    public long getItemId(int position) {
        return position;
    }
    

    after that remove animation began to work

    0 讨论(0)
  • 2020-12-23 19:46

    I ran into same issue, and I fixed this by implementing my own RecyclerView, and in my recyclerview, I did this:

    public class MyRecyclerView extends RecyclerView {
       private View mEmptyView;
       private AdapterDataObserver mDataObserver = new AdapterDataObserver() {
           public void onChanged() {
              super.onChanged();
              updateEmptyView();
           }
    
           public void onItemRangeRemoved(int positionStart, int itemCount) {
               super.onItemRangeRemoved(positionStart, itemCount);
               updateEmptyView();
           }
    
           public void onItemRangeInserted(int positionStart, int itemCount) {
              super.onItemRangeInserted(positionStart, itemCount);
              updateEmptyView();
           }
         };
    
        // private void setAdapter() {}
    
        private void updateEmptyView() {
             // update empty view's visibility
        }
    
    }
    

    Basically, when you add/remove item into/from recyclerview, you can call notifyItemInserted()/ notifyItemRemoved() and notifyItemRangeChanged(), these method will invoke onItemRangeRemoved() / onItemRangeInserted() in mDataObserver. So in these method, you can update empty view's visibility, and it will not break animations.

    0 讨论(0)
  • 2020-12-23 19:50

    I was able to remove the view with the animation and updated indices as follows:

    Within the adapter,

    public boolean removeItem(int position) {
        if (data.size() >= position + 1) {
            data.remove(position);
            return true;
        }
        return false;
    }
    

    While removing the views, call

    if (adapter.removeItem(position)) {
        adapter.notifyItemRemoved(position);
        adapter.notifyItemRangeChanged(position, adapter.getItemCount());
    }
    

    I have used a boolean method to ensure that double clicks,etc. don't cause a crash.

    0 讨论(0)
提交回复
热议问题