9

I have a ReyclerView working with a LinearLayoutManager and an Adapter<ViewHolder>. I have a list of items I would like to display in the recyclerview with the insert (slide in) animation. How do I go about this ?

I would like to display the animations with a linearly increasing delay based on the index of the item.

Currently, if I use 2 buttons, 'add' and 'remove', and then do the respective operations on the recyclerview (notifyItemInserted() and notifyItemRemoved(), the animations come in nicely.

If I programmatically loop on the data set and add the items, again, using notifyItemInserted(), I do not see any animation. I just see all the items appear almost at once.

If I use Asynctasks with linear delay, and then add/remove the item in OnPostExecute(), I still do not see any animation. Also, I see a possibility of running into deadlocks if multiple insert threads are waiting on all remove threads to be completed (with no place for the remove threads to run).

What am I doing wrong ?

I have gone through most of the questions related to this on SO and have spent days poking around the animation part of the recyclerview, still no luck.

Marcus
  • 6,697
  • 11
  • 46
  • 89
milindbableshwar
  • 256
  • 1
  • 3
  • 9

3 Answers3

11

Below is how I add an animation in my Adapter. This will animate a push effect, with the row coming in from the right.

First define the animation in xml (res/anim/push_left_in.xml)

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="100%p" android:toXDelta="0"
        android:duration="300"/>
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
        android:duration="300" />
</set>

Then set it in your Adapter as so

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row;
    if (convertView == null) {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        row = inflater.inflate(R.layout.music_list_item, null);
    } else {
        row = convertView;
    }

    ...

    //Load the animation from the xml file and set it to the row
    Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.push_left_in);
    animation.setDuration(500);
    row.startAnimation(animation);

    return row;
}

This animation will be displayed each time you add a new row, it should work in your case.

Edit

This is how you could add an animation using a RecyclerView

@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
    holder.text.setText(items.get(position));

    // Here you apply the animation when the view is bound
    setAnimation(holder.container, position);
}

/**
 * Here is the key method to apply the animation
 */
private void setAnimation(View viewToAnimate, int position)
{
    // If the bound view wasn't previously displayed on screen, it's animated
    if (position > lastPosition)
    {
        Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.push_left_in);
        viewToAnimate.startAnimation(animation);
        lastPosition = position;
    }
}
Marcus
  • 6,697
  • 11
  • 46
  • 89
  • 1
    Have a look at [this answer](http://stackoverflow.com/questions/26724964/how-to-animate-recyclerview-items-when-they-appear). The author explains where to add the animation when you are using a `RecyclerView`. @milindbableshwar – Marcus Mar 11 '15 at 13:54
  • I've edit the relevant code to my answer, please have a look. @milindbableshwar – Marcus Mar 11 '15 at 13:56
  • Perfect! This is working. A follow up question, how do animate item deletions ? I mean, if I were to programmatically remove the list of items, where should I start the remove item animation ? – milindbableshwar Mar 11 '15 at 14:20
  • Unfortunately, I do not know. I did some research but could not find any relevant answers. I believe that it's fit to create a new question to address this matter. @milindbableshwar – Marcus Mar 11 '15 at 17:49
  • 1
    how is lastPosition initialized or defined? I'm assuming it's (position - 1) defined as a method variable. – Futureproof Feb 12 '16 at 18:54
4

Add this line to your RecyclerView xml:

android:animateLayoutChanges="true"

penduDev
  • 4,743
  • 35
  • 37
1

This works for me:

animation.setStartOffset(position*100);
Jonas Czech
  • 12,018
  • 6
  • 44
  • 65