滚动时动画RecyclerView

时间:2014-08-19 09:24:57

标签: android android-animation android-recyclerview

滚动时,有没有办法为RecyclerView的元素设置动画?

我看了DefaultItemAnimatorRecyclerView.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总是假的,所以没有达到任何回调。知道如何正确设置设置标志吗?

3 个答案:

答案 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