滚动时,有没有办法为RecyclerView的元素设置动画?
我看了DefaultItemAnimator
和RecyclerView.ItemAnimator
,但是如果数据集发生变化,动画似乎只会被调用,如果我错了,请纠正我。
我对RecyclerView.ItemAnimator.animateMove()
何时被称为有点困惑?我在该课程中加入了一些断点,但没有一个断点停止我的应用程序。
然而,回到我的问题,如何为RecyclerView设置动画?我希望某些元素具有另一个不透明度,取决于一些自定义规则。
我做了一些更多的事情似乎动画移动正是我正在寻找的。这些方法是从dispatchLayout()
调用的。这是该方法的javadoc:
layoutChildren()周围的包装器,用于处理由布局引起的动画更改。 动画假设有五种不同的项目 在游戏中:
PERSISTENT:项目在布局之前和之后可见 删除:项目在布局之前可见,并由应用程序删除 增加:项目在布局之前不存在,并由应用程序添加 DISAPPEARING:项目存在于之前/之后的数据集中,但是从中更改 在布局过程中可见不可见(它们被移开了 屏幕作为其他变化的副作用)
出现:项目存在于之前/之后的数据集中,但已从中更改 在布局过程中看不到可见的(他们被移动了 屏幕作为其他变化的副作用)
整体方法确定布局之前/之后存在哪些项目 推断每个项目的上述五种状态之一。然后是动画 相应设置:
移动了PERSISTENT视图({@link ItemAnimator#animateMove(ViewHolder,int,int,int,int)}) 删除了已删除的视图({@link ItemAnimator#animateRemove(ViewHolder)})
添加了添加的视图({@link ItemAnimator#animateAdd(ViewHolder)})
消失视图从屏幕上移开
外观视图在屏幕上移动
到目前为止,我一直在寻找PERSISTENT,DISAPPEARING和APPEARING,但是因为这一行所以永远不会调用这些方法:
boolean animateChangesSimple = mItemAnimator != null && mItemsAddedOrRemoved
&& !mItemsChanged;
mItemsAddedOrRemoved
总是假的,所以没有达到任何回调。知道如何正确设置设置标志吗?
答案 0 :(得分:9)
我最终使用了OnScrollListener
并在自定义animate()
方法中设置了动画。在我的情况下,代码只需2毫秒,因此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();
}
});
答案 1 :(得分:6)
<强>更新强>
要修复快速滚动行为,请覆盖适配器的onViewDetachedFromWindow
方法,并在动画视图上调用clearAnimation
(在本例中为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>
最后将此代码放在onBindViewHolder
的{{1}}中。创建一个名为lastPosition的字段并将其初始化为-1。
recyclerView
答案 2 :(得分:0)
好的解决方案是使用onBindViewHolder
方法在适配器中为持有者设置动画。
从材料测试项目中获取的片段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;
这是一个link