首页 文章

滚动时动画RecyclerView

提问于
浏览
24

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

我看了 DefaultItemAnimatorRecyclerView.ItemAnimator ,但是如果数据集发生了变化似乎只调用了动画,如果我错了请纠正我 .

关于 RecyclerView.ItemAnimator.animateMove() 我什么时候打电话给我有点困惑?我在该课程中添加了一些断点,但没有一个断点停止我的应用程序 .

但是回到我的问题,我如何为RecyclerView设置动画?我希望某些元素具有另一个不透明度,取决于一些自定义规则 .


我做了一些更多的动画似乎动画移动正是我正在寻找的 . 这些方法从 dispatchLayout() 调用 . 这是该方法的javadoc:

layoutChildren()周围的包装器,用于处理由布局引起的动画更改 . 动画假设有五种不同类型的项目:PERSISTENT:项目在布局之前和之后可见REMOVED:项目在布局之前可见并且被应用程序删除ADDED:项目在布局之前不存在并且由应用程序DISAPPEARING:项目存在于数据集之前/之后,但在布局过程中从可见变为不可见(它们被移出屏幕作为其他更改的副作用)出现:数据集中存在项目之前/之后,但在布局过程中从不可见变为可见(它们在屏幕上移动作为其他变化的副作用)整体方法确定布局之前/之后存在哪些项目并推断五个中的一个以上状态为每个项目 . 然后相应地设置动画:移动PERSISTENT视图({@link ItemAnimator #animateMove(ViewHolder,int,int,int,int)})删除REMOVED视图({@link ItemAnimator #animateRemove(ViewHolder)})ADDED视图添加({@link ItemAnimator#animateAdd(ViewHolder)})DISAPPEARING视图移出屏幕在屏幕上移动视图

到目前为止,我正在寻找PERSISTENT,DISAPPEARING和APPEARING,但是这个方法从未被调用,因为这里有这一行:

boolean animateChangesSimple = mItemAnimator != null && mItemsAddedOrRemoved
            && !mItemsChanged;

mItemsAddedOrRemoved 总是假的,所以没有达到任何回调 . 知道如何正确设置设置标志吗?

3 回答

  • 0

    我最终使用 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();
        }
    });
    
  • 6

    我是这样做的 . 可以帮助别人 . 我不知道这是否是最好的方式,但对我来说效果很好 .

    UPDATE: 要修复快速滚动行为,请覆盖适配器的 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>
    

    最后将此代码放在 recyclerViewrecyclerView 中 . 创建一个名为lastPosition的字段并将其初始化为-1 .

    Animation animation = AnimationUtils.loadAnimation(context,
                (position > lastPosition) ? R.anim.up_from_bottom
                        : R.anim.down_from_top);
        holder.itemView.startAnimation(animation);
        lastPosition = position;
    
  • 9

    好的解决方案是在 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

相关问题