【问题标题】:How can you animate recyclerview items when scrolling?滚动时如何为 recyclerview 项目设置动画?
【发布时间】: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;

}

【问题讨论】:

  • 你找到解决办法了吗?

标签: android animation android-recyclerview onscrolllistener


【解决方案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 时为膨胀视图设置动画的东西
猜你喜欢
  • 1970-01-01
  • 2014-10-12
  • 2014-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多