How to Animate Recyclerview Items When They Appear

How to animate RecyclerView items when they appear

Made Simple with XML only

Visit Gist Link

res/anim/layout_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_fall_down"
android:animationOrder="normal"
android:delay="15%" />

res/anim/item_animation_fall_down.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500">

<translate
android:fromYDelta="-20%"
android:toYDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
/>

<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:anim/decelerate_interpolator"
/>

<scale
android:fromXScale="105%"
android:fromYScale="105%"
android:toXScale="100%"
android:toYScale="100%"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/decelerate_interpolator"
/>

</set>

Use in layouts and recylcerview like:

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_animation"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />

How to animate RecyclerView items when adapter is initialized (in order)?

After you call setAdapter you can run following:

recyclerView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {

@Override
public boolean onPreDraw() {
recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);

for (int i = 0; i < recyclerView.getChildCount(); i++) {
View v = recyclerView.getChildAt(i);
v.setAlpha(0.0f);
v.animate().alpha(1.0f)
.setDuration(300)
.setStartDelay(i * 50)
.start();
}

return true;
}
});

Example shows simple alpha animation, but you can run what you want in the loop and adjust interpolator, duration and start delay.

Animating recyclerView items

I don't know why everyone is fascinated about putting everything into RecyclerView.Adapter.

You can inject this animation into RecyclerView.LayoutManager instead as it is aware of exact moment and position where views are added:

open class FadeInLinearLayoutManager : LinearLayoutManager {
constructor(context: Context?) : super(context)
constructor(context: Context?, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

private val enterInterpolator = AnticipateOvershootInterpolator(2f)

override fun addView(child: View, index: Int) {
super.addView(child, index)
val h = 400f
// if index == 0 item is added on top if -1 it's on the bottom
child.translationY = if(index == 0) -h else h
// begin animation when view is laid out
child.alpha = 0.3f
child.animate().translationY(0f).alpha(1f)
.setInterpolator(enterInterpolator)
.setDuration(1000L)
}
}

Then use it as your layout manager:

recyclerView.layoutManager = FadeInLinearLayoutManager(context)

Animate changes in row layout of in a RecyclerView

Keep android:animateLayoutChanges="true" in your custom row. When you want to animate the trashcan in or out ensure that the bind logic will set the icon to visible or gone as needed on the next bind.

To force the animations, notify the adapter as follows:

myAdapter.notifyItemRangeChanged(0, items.size, true)

where

items is your list of data.

true is the payload parameter that will trigger the animation. This argument just must not be null and you can tailor it to your needs.

See notifyitemchanged.

The animation can be controlled with ViewGroup#getLayoutTransition() although there are default values that may be acceptable. For instance, to change the animation duration to one second, place the following in your adapter:

[your itemView].layoutTransition?.apply { setDuration(1000) }

I posted a small app on GitHub to demonstrate this technique.

Sample Image

Animate RecyclerView items one by one

How about this:

public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
myHolder = holder as MyView;
if (position > mCurrentPosition)
{
Handler h = new Handler();
int currentAnim = Android.Resource.Animation.SlideInLeft;
Action myAction = () =>
{
SetAnimation(holder.ItemView, currentAnim);
};

h.PostDelayed(myAction, 1000);


mCurrentPosition = position;
}

}

Update: if you want to animate all items in order, you should put logic code out side an adapter.

For example, in activity, after set adapter for RecyleView

   List<YourObject> data; // your data list for RecycleView

// CALL this code after set adapter for RecycleView
Handler h = new Handler();
int currentAnim = Android.Resource.Animation.SlideInLeft;
Action myAction = () =>
{
// assume you use LinearLayoutManager for RecyecleView
View itemView = linearLayoutManager.findViewByPosition(0);
StartAnimation(itemView, 0);
};

h.PostDelayed(myAction, 1000);


private void StartAnimation(View view, int position)
{

Animation anim = AnimationUtils.LoadAnimation(mContext, currentAnim);
anim.SetInterpolator(mContext, Android.Resource.Interpolator.Bounce);
view.StartAnimation(anim);
anim.AnimationEnd += (sender, e) =>
{
// animate next item

++position;
if (position < data.size()) // data is your array list
{

// assume you use LinearLayoutManager for RecyecleView
View itemView = linearLayoutManager.findViewByPosition(position);
if (itemView != null)
{
StartAnimation(itemView, position);
}
}
}
}


Related Topics



Leave a reply



Submit