No animation on item removal on RecyclerView

android recyclerview item animation
android recyclerview item animation example
android recyclerview selected item animation
android-recyclerview item move animation
recyclerview animation github
recyclerview remove item example
recyclerview predictive animations
recyclerview slide in animation

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 addition works just fine.

I have not set any custom item animator, but according to the documentation:

Animations for adding and removing items are enabled by default in RecyclerView.

So the animations on removal should work.

I would like to have the default animation on removal, but can't get that to work.

This is how I setup the RecyclerView:

private void setupRecyclerView() {
  mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.recycler_view);
  mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
  View emptyView = mRootView.findViewById(R.id.empty_view);
  mAdapter = new RoutineAdapter(getActivity(), mRoutineItems, emptyView);
  mRecyclerView.setAdapter(mAdapter);
}

This is my adapter:

private class RoutineAdapter
      extends RecyclerView.Adapter<RoutineAdapter.ViewHolder> {

private final Context mContext;
private List<RoutineItem> mData;
private View mEmptyView;

    public RoutineAdapter(Context context, List<RoutineItem> data, View emptyView) {
      mContext = context;
      mData = data;
      mEmptyView = emptyView;
      setEmptyViewVisibility();
    }

    public void add(RoutineItem routineItem, int position) {
      mData.add(position, routineItem);
      setEmptyViewVisibility();
      notifyItemInserted(position);
    }

    public void remove(int position){
      mData.remove(position);
      setEmptyViewVisibility();
      notifyItemRemoved(position);
    }

    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      final View view = LayoutInflater.from(mContext).inflate(
          R.layout.fragment_routines_list_item, parent, false);
      return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
      final RoutineItem routineItem = getItem(position);
      holder.circle.setBackgroundResource(
          colorNumberToDrawableResource(routineItem.colorNumber));
      holder.initial.setText(routineItem.routineName.substring(0, 1));
      holder.routineName.setText(routineItem.routineName);
      holder.lastTimeDone.setText(routineItem.lastTimeDoneText);
      if (routineItem.isSelected) {
        holder.itemView.setBackgroundColor(
            getResources().getColor(R.color.background_item_selected));
      } else {
        holder.itemView.setBackgroundResource(
            R.drawable.darker_background_on_pressed);
      }
      holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          mPresenter.onRoutineClicked(routineItem.routineName);
        }
      });
      holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
          mPresenter.onRoutineLongClicked(routineItem.routineName);
          return true;
        }
      });
    }

    @Override
    public int getItemCount() {
      return mData.size();
    }

    public RoutineItem getItem(int position) {
      return mData.get(position);
    }

    private void setEmptyViewVisibility() {
      if (getItemCount() == 0) {
        mEmptyView.setVisibility(View.VISIBLE);
      } else {
        mEmptyView.setVisibility(View.GONE);
      }
    }

    class ViewHolder extends RecyclerView.ViewHolder {
      public final View circle;
      public final TextView initial;
      public final TextView routineName;
      public final TextView lastTimeDone;

      public ViewHolder(View view) {
        super(view);
        circle = view.findViewById(R.id.circle);
        initial = (TextView) view.findViewById(R.id.initial);
        routineName = (TextView) view.findViewById(R.id.routine_name);
        lastTimeDone = (TextView) view.findViewById(R.id.last_time_done);
      }
    }
}

Fragment_routines_list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:minHeight="@dimen/standard_list_item_height"
  android:paddingBottom="8dp"
  android:background="@drawable/darker_background_on_pressed"
  android:clickable="true">
    ......
</RelativeLayout>

What am I doing wrong that causes the default removal animation to not work?

The proper way to remove an item from recycler view is to remove the item from data set and then telling the adapter that the item is removed like so

myDataset.remove(position); // myDataset is List<MyObject>
mAdapter.notifyItemRemoved(position);

RecyclerView Animations - Add & Remove Items, Let's begin by creating a simple RecyclerView implementation. We'll have a simple text item which will have some buttons to add and remove  I have the RecyclerView, ItemTouchHelper and ItemTouchHelper.Callback instances to work together, and on swipe to left the selected item supposed to be removed ( by this tutorial ). The removal animation works, but only partly. First after swipe the item seems to be removed,

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.

Simultaneous Insertion and Removal in RecyclerView with Animation, remove item 1, 2 and 4), or if we want to perform insertion and removal simultaneously, and have it animated accordingly, how to achieve that? There's no  Then we call notifyDataSetChanged() which informs the RecyclerView that something has changed and it updates the list. If we don’t call this then the update is not shown. If we run this we see the basic behaviour: We can see the basic add and remove behaviour, but no nice animations.

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

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

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

Yes, recyclerview has default animations for view holders' change , We can disable default fade in/out animation to avoid blinks.. This happens due to item animator in recycler view. 80. 2. Daya Nand Yes, recyclerview has default animations for view holders' change, insert and remove operations! We can  If supportsChangeAnimations is false, the old and new viewHolders will however be the same object, and there will instead be an onMoved animation from x to x (i.e., no actual move). This however means that the item will get an annoying bounce effect.

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.

DefaultItemAnimator, ItemAnimator provides basic animations on remove, add, and move events that Called when an item is removed from the RecyclerView. Animating items in the recyclerview when they are binded in the adapter might not be the best idea as that can cause the items in the recyclerview to animate at different speeds. In my case, the item at the end of the recyclerview animate to their position quicker then the ones at the top as the ones at the top have further to travel so it made it look untidy.

Another reason for a not properly working remove animation could be the RecyclerViews height. Verify that the height is match_parent and NOT wrap_content!

RecyclerView, Throughout this post I will explain how to initiate default RecyclerView animations​. Item removal is animated by fading it out, insertion by fading it in, movement by More efficient means that no extra view will be bound (or maybe even  Enter animation using RecyclerView and LayoutAnimation Part 3: Exclude items Introduction In this tutorial we’ll learn an easy way to add an initial content animation for a RecyclerView.

RecyclerView animations, So in case which we described earlier (remove item operation) the most bottom element was not shifted because it hadn't existed before. In this  Using ItemAnimators. – Read this tutorial. Setting animation on each row in the onBindViewHolder in the Adapter class; There’s another lesser-known but more efficient way of animating a RecyclerView using Layout Animations.

Add and remove items to RecyclerView, with default animation , An Android Animation library which easily add itemanimator to RecyclerView items. #179 animation not worked properly when i put recyclerview inside nested  Subclasses of ItemAnimator can be used to implement custom animations for actions on ViewHolder items. The RecyclerView will manage retaining these items while they are being animated, but implementors must call dispatchAnimationFinished(ViewHolder) when a ViewHolder's animation is finished.

wasabeef/recyclerview-animators: An Android Animation , Recycler views animate the adding and removing of elements automatically. Now, outside the recycler view, you can add and remove from stringList via the standard You also need to scroll to that item, else it will just be inserted about the  RecyclerView Animators is an Android library that allows developers to easily create RecyclerView with animations. Please feel free to use this. Animate addition and removal of ItemAnimator. Appearance animations for items in RecyclerView.Adapter. How do I use it? On your module's build.gradle file add this implementation statement to the

Comments
  • And indices will get messed up if you don't.
  • The solution to fix this problem is to use viewHolder.getAdapterPosition() for onClick instead of position passed in inside of onBindViewHolder
  • but the adapter will lost positions of other items in the list and when you try deleting another item as at that moment, it will remove the item below it, also if there is no item below it, then it will crash. pls confirm that.
  • myDataset.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, youDataSets.size()); use this code, this will solve your problem.
  • That's another reason. The insert animation works with wrap_content but not the removal one. Any way to workaround this?