Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView : How to create insert animation effect?

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.

like image 511
milindbableshwar Avatar asked Mar 11 '15 12:03

milindbableshwar


3 Answers

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;
    }
}
like image 188
Marcus Avatar answered Oct 22 '22 20:10

Marcus


This works for me:

animation.setStartOffset(position*100);
like image 20
Paul Osinga Avatar answered Oct 22 '22 19:10

Paul Osinga


Add this line to your RecyclerView xml:

android:animateLayoutChanges="true"

like image 35
penduDev Avatar answered Oct 22 '22 20:10

penduDev