Animate RecyclerView when scrolling
Solution 1
I ended in using an OnScrollListener
and animating it in a custom animate()
method. In my case that code takes just 2ms so that is no problem for the 60fps.
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(int newState) {
if(newState == RecyclerView.SCROLL_STATE_IDLE) {
// special handler to avoid displaying half elements
scrollToNext();
}
animate();
}
@Override
public void onScrolled(int dx, int dy) {
animate();
}
});
Solution 2
I did it this way. Might help someone. I don't know whether it's the best way to do it but works fine for me.
UPDATE:
To fix fast scrolling behaviour, override onViewDetachedFromWindow
method of the adapter and call clearAnimation
on the animated view (in this case, holder.itemView.clearAnimation()
).
up_from_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="@android:anim/decelerate_interpolator">
<translate
android:fromXDelta="0%" android:toXDelta="0%"
android:fromYDelta="100%" android:toYDelta="0%"
android:duration="400" />
</set>
down_from_top.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="@android:anim/decelerate_interpolator">
<translate
android:fromXDelta="0%" android:toXDelta="0%"
android:fromYDelta="-100%" android:toYDelta="0%"
android:duration="400" />
</set>
And finally put this code in onBindViewHolder
of recyclerView
. Create a field called lastPosition and initialize it to -1.
Animation animation = AnimationUtils.loadAnimation(context,
(position > lastPosition) ? R.anim.up_from_bottom
: R.anim.down_from_top);
holder.itemView.startAnimation(animation);
lastPosition = position;
Related videos on Youtube
![rekire](https://i.stack.imgur.com/UPzx8.png?s=256&g=1)
rekire
Check also my gists and projects on GitHub. Voice related Apps: REWE✝ (Google, Amazon) CentralStation CRM (Google (DE), Google (US), Amazon (DE), Amazon (US)) List of my Apps or Apps I worked on: snabble by snabble CentralPlanner by 42he (flutter) gooods by snabble toom by snabble CentralStation CRM by 42he Zykluskalender✝ by NetMoms Hotel Search by HRS REWE Lieferservice, Supermarkt by REWE Digital BILLA Online Shop✝ by REWE Digital CentralStation CRM by 42he ✝ = Reached end of life Open source projects where I am involved: Author of Konversation intent-schema-generation provisioning cli kotlin-multi-platform Contributor of dialog dialogflow alexa kotlin Author of LazyWorker android tool Contributor of Futter flutter You want to hire me? Check my careers profile.
Updated on July 11, 2022Comments
-
rekire almost 2 years
Is there any way to animate the elements of a RecyclerView when I scroll it?
I took a look at
DefaultItemAnimator
andRecyclerView.ItemAnimator
, but that animations seems to be only called if the dataset has changed, please correct me if I am wrong.I'm a little confused about
RecyclerView.ItemAnimator.animateMove()
when is it called? I put some breakpoints into that class but none of them stops my app.However back to my question how can I animate the RecyclerView? I want that some elements have another opacity, depended on some custom rules.
I did some more reaseach it seems that animation move is exactly that what I'm looking for. That methods are called from
dispatchLayout()
. Here is the javadoc of that method:Wrapper around layoutChildren() that handles animating changes caused by layout. Animations work on the assumption that there are five different kinds of items in play:
PERSISTENT: items are visible before and after layout
REMOVED: items were visible before layout and were removed by the app
ADDED: items did not exist before layout and were added by the app
DISAPPEARING: items exist in the data set before/after, but changed from visible to non-visible in the process of layout (they were moved off screen as a side-effect of other changes)
APPEARING: items exist in the data set before/after, but changed from non-visible to visible in the process of layout (they were moved on screen as a side-effect of other changes)
The overall approach figures out what items exist before/after layout and infers one of the five above states for each of the items. Then the animations are set up accordingly:
PERSISTENT views are moved ({@link ItemAnimator#animateMove(ViewHolder, int, int, int, int)}) REMOVED views are removed ({@link ItemAnimator#animateRemove(ViewHolder)})
ADDED views are added ({@link ItemAnimator#animateAdd(ViewHolder)})
DISAPPEARING views are moved off screen
APPEARING views are moved on screenSo far I'm looking for PERSISTENT, DISAPPEARING and APPEARING, but that methods are never called because of this line here:
boolean animateChangesSimple = mItemAnimator != null && mItemsAddedOrRemoved && !mItemsChanged;
mItemsAddedOrRemoved
is simply always false so none of that callback are ever reached. Any idea how to set set flag correctly?-
raj almost 10 yearsyou can use objectanimtor introduced in api11 for animating any object
-
rekire almost 10 yearsWell fine but how do I know when I need to start the animation?
-
-
MaTriXy over 9 yearscan you add a bit more code - like scrollToNext for example?
-
rekire over 9 yearsThat is out of the scope of my question. You should ask a independ question about that. Keep in mind to show your current progress while implementing that :)
-
Mostafa Rostami almost 8 yearsThis solution for a certain library not for all.
-
Aung Thiha about 7 yearsthe animation show up again when notifiydatasetchange. Any way to fix it?
-
Sandip Fichadiya almost 7 years@rekire can you please help me with my question:stackoverflow.com/questions/45858059/…