Is there any way to animate the elements of a RecyclerView when I scroll it?
I took a look at DefaultItemAnimator
and RecyclerView.ItemAnimator
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;
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();
}
});
The good solution is to animate holder in adapter in onBindViewHolder
method.
Snippet taken from Material Test project Slidenerd:
@Override
public void onBindViewHolder(ViewHolderBoxOffice holder, int position) {
Movie currentMovie = mListMovies.get(position);
//one or more fields of the Movie object may be null since they are fetched from the web
holder.movieTitle.setText(currentMovie.getTitle());
//retrieved date may be null
Date movieReleaseDate = currentMovie.getReleaseDateTheater();
if (movieReleaseDate != null) {
String formattedDate = mFormatter.format(movieReleaseDate);
holder.movieReleaseDate.setText(formattedDate);
} else {
holder.movieReleaseDate.setText(Constants.NA);
}
int audienceScore = currentMovie.getAudienceScore();
if (audienceScore == -1) {
holder.movieAudienceScore.setRating(0.0F);
holder.movieAudienceScore.setAlpha(0.5F);
} else {
holder.movieAudienceScore.setRating(audienceScore / 20.0F);
holder.movieAudienceScore.setAlpha(1.0F);
}
if (position > mPreviousPosition) {
AnimationUtils.animateSunblind(holder, true);
} else {
AnimationUtils.animateSunblind(holder, false);
}
mPreviousPosition = position;
here is a link