滚动时如何为 recyclerview 项目设置动画?

Posted

技术标签:

【中文标题】滚动时如何为 recyclerview 项目设置动画?【英文标题】:How can you animate recyclerview items when scrolling? 【发布时间】:2016-11-01 13:37:15 【问题描述】:

我正在使用 RecyclerView 和自定义 RecyclerViewOnScrollListener。 我想在向下滚动时更改 RecyclerView 项目高度,并在向上滚动时返回到原始高度。

我已经在同一个侦听器中为底部栏设置动画,但我不明白如何为 RecyclerView 中的每个项目设置动画。我尝试过使用 for 循环,但我认为这不是正确的想法。

public abstract class RecyclerViewOnScrollListener extends RecyclerView.OnScrollListener 

    private LinearLayout bottomBarContainer;
    private boolean animateItems = false;
    CardStackLayoutManager cardStackLayoutManager;
    public RecyclerViewOnScrollListener(LinearLayout bottomBarContainer) 
        this.bottomBarContainer = bottomBarContainer;
    

    public RecyclerViewOnScrollListener(LinearLayout bottomBarContainer, boolean animateItems, CardStackLayoutManager cardStackLayoutManager) 
        this.bottomBarContainer = bottomBarContainer;
        this.animateItems = animateItems;
        this.cardStackLayoutManager = cardStackLayoutManager;
    

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) 
        super.onScrolled(recyclerView, dx, dy);

        if (bottomBarContainer==null || dy==0 ) 
            return;
        
        long ANIMATION_DURATION = 200L;
        if (dy>0)  // Scrolling to bottom

            if (mIsScrollDirectionLocked && mScrollingDirection!=0) return;

            if (bottomBarContainer.getVisibility()== View.GONE || mIsAnimatingOff) 
                return;
             else 
                for(int i = 0;i < cardStackLayoutManager.getChildCount();i++)
                
                    View view = cardStackLayoutManager.getChildAt(i);
                    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,"y",0f,200f);
                    objectAnimator.setDuration(150);
                    objectAnimator.start();
                
                mScrollingDirection = SCROLLING_DOWN;
                mIsAnimatingOff = !mIsAnimatingOff;

                ViewCompat.setTranslationY(bottomBarContainer, 0F);

                ViewCompat.animate(bottomBarContainer)
                        .translationY(bottomBarContainer.getHeight())
                        .setDuration(ANIMATION_DURATION)
                        .setListener(new ViewPropertyAnimatorListenerAdapter() 
                            @Override
                            public void onAnimationEnd(View view) 
                                mIsAnimatingOff = !mIsAnimatingOff;
                                bottomBarContainer.setVisibility(View.GONE);
                            
                        ).start();

            
         else  // Scrolling to top
            if (mIsScrollDirectionLocked && mScrollingDirection!=0) return;

            if (bottomBarContainer.getVisibility()!=View.VISIBLE && !mIsAnimatingOn) 

                mScrollingDirection = SCROLLING_UP;
                mIsAnimatingOn = !mIsAnimatingOn;
                bottomBarContainer.setVisibility(View.VISIBLE);
                for(int i = 0;i < cardStackLayoutManager.getChildCount();i++)
                
                    View view = cardStackLayoutManager.getChildAt(i);
                    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,"y",200f,0f);
                    objectAnimator.setDuration(150);
                    objectAnimator.start();
                
                ViewCompat.setTranslationY(bottomBarContainer, bottomBarContainer.getHeight());

                ViewCompat.animate(bottomBarContainer)
                        .translationY(0F)
                        .setDuration(ANIMATION_DURATION)
                        .setListener(new ViewPropertyAnimatorListenerAdapter() 
                            @Override
                            public void onAnimationEnd(View view) 
                                mIsAnimatingOn = !mIsAnimatingOn;
                            
                        ).start();
            
        
    

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) 
        super.onScrollStateChanged(recyclerView, newState);
        if (!mIsScrollDirectionLocked) return;

        switch (newState) 
            case RecyclerView.SCROLL_STATE_IDLE:
                mScrollingDirection = 0;
                break;
            default:
                break;
        
    

    private static final int SCROLLING_UP = 1;

    private static final int SCROLLING_DOWN = 2;

    private int mScrollingDirection = 0;

    private boolean mIsScrollDirectionLocked = false;

    private boolean mIsAnimatingOff = false;

    private boolean mIsAnimatingOn = false;


【问题讨论】:

你找到解决办法了吗? 【参考方案1】:

定义一个方法来为您的ConvertView 设置动画,如下所示:

private void setAnimation(View viewToAnimate,int position) 
      if (position > lastPosition) 
         lastPosition = position;
         Animation animation = AnimationUtils.loadAnimation(activity, R.anim.anim_content);
         viewToAnimate.startAnimation(animation);
      

并在您的适配器的onBindViewHolder 方法中调用您的动画方法:

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) 
     // Do your initialization
     setAnimation(holder.convertView, position);

这是动画:(anime_content.xml)

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="25%p"
    android:toYDelta="0%p"
    android:duration="300"
    android:interpolator="@android:anim/decelerate_interpolator" />

这个例子将动画你最后一个膨胀的回收器视图行从下到上。您可以随意更改动画。

祝你好运!

【讨论】:

您好,感谢您的回答。此实现仅在 recyclerView 项目第一次膨胀时起作用。我想要一些动画来响应 onScroll..比如向下滚动时增加高度并在向上滚动时减少 是的,这是 recyclerview 的行膨胀动画实现。 我正在寻找在滚动 recyclerview 时为膨胀视图设置动画的东西

以上是关于滚动时如何为 recyclerview 项目设置动画?的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 应用程序中单击时如何为下拉按钮中的项目设置填充

弹出键盘时如何为 UITableView 设置动画?

序列化时如何为循环值设置null

更改设备方向时如何为uiimageview设置动画

加载 WebView 页面时如何为警报对话框设置不同的标题?

转换ghostscript光栅化器时如何为Jpeg设置dpi