【问题标题】:How to animate RecyclerView items when adapter is initialized (in order)?初始化适配器时如何为 RecyclerView 项目设置动画(按顺序)?
【发布时间】:2016-12-18 23:17:52
【问题描述】:

我正在努力实现的目标

我想让线性垂直 RecyclerView 中的项目按顺序显示。我希望第一个项目出现,然后是第二个,然后是第三个,依此类推。这是我尝试完成的动画类型的示例。


我的尝试

我已经尝试过这个问题中提供的方法:How to animate RecyclerView items when they appear

但是,这并不是我想要完成的。这会导致 RecyclerView 中的所有项目同时出现,而不是一次出现一个。


我的代码

public class ParentCommentsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private int lastPosition = -1;

    //constructor and other code not shown...

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        switch (viewHolder.getItemViewType()) {
            case OP:
                OPViewHolder ovh = (OPViewHolder) viewHolder;
                configureOPViewHolder(ovh, position);
                setAnimation(ovh.getContainer(), position);
                break;
            case COMMENT:
                CommentViewHolder cvh = (CommentViewHolder) viewHolder;
                configureCommentViewHolder(cvh, position);
                setAnimation(cvh.getContainer(), position);
                break;
            default:
                RecyclerViewSimpleTextViewHolder vh = (RecyclerViewSimpleTextViewHolder) viewHolder;
                configureDefaultViewHolder(vh, position);
                break;
        }

    }

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder viewHolder)
    {

        switch (viewHolder.getItemViewType()) {
            case OP:
                ((OPViewHolder)viewHolder).clearAnimation();
                break;
            case COMMENT:
                ((CommentViewHolder)viewHolder).clearAnimation();
                break;
            default:
                break;
        }
    }

    private void configureDefaultViewHolder(RecyclerViewSimpleTextViewHolder vh, int position) {
        //code...
    }

    private void configureOPViewHolder(OPViewHolder vh1, int position) {
        //code...
    }

    private void configureCommentViewHolder(CommentViewHolder vh2, int position) {
        //code...
    }

    private void setAnimation(View viewToAnimate, int position)
    {
        // If the bound view wasn't previously displayed on screen, it's animated
        if (position > lastPosition)
        {
            Animation animation = AnimationUtils.loadAnimation(context, R.anim.fade_in);
            viewToAnimate.startAnimation(animation);
            lastPosition = position;
        }
    }

}

【问题讨论】:

  • 你考虑过像github.com/wasabeef/recyclerview-animators这样的OSS项目吗?
  • @SebastianRoth 我在研究时确实遇到了那个项目。该项目似乎有很多动画,但我已经有了自己想要使用的动画。我的问题是我希望 recyclerview 项目在最初打开活动时按顺序设置动画。因此,当活动打开时,我希望第一项动画,然后是第 2 项,然后是第 3 项,依此类推。

标签: android


【解决方案1】:

调用setAdapter 后,您可以运行以下命令:

recyclerView.getViewTreeObserver().addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {

            @Override
            public boolean onPreDraw() {
                recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);

                for (int i = 0; i < recyclerView.getChildCount(); i++) {
                    View v = recyclerView.getChildAt(i);
                    v.setAlpha(0.0f);
                    v.animate().alpha(1.0f)
                            .setDuration(300)
                            .setStartDelay(i * 50)
                            .start();
                }

                return true;
            }
        });

示例显示了简单的 alpha 动画,但您可以在循环中运行所需的内容并调整插值器、持续时间和开始延迟。

【讨论】:

  • 效果很好,我只是用自己的动画替换了动画。看起来关键是添加 setStartDelay 选项并相对于项目位置更改延迟。非常感谢你,尼科。
  • 有没有办法删除 OnPreDrawListener?假设我以后想使用不同的动画,我该怎么做?我尝试添加与此处相同但具有不同动画的不同方法,但它似乎只是在当前动画之上添加了该动画。
  • 这是调用setAdapter后的一次触发,在onPreDraw方法中调用removeOnPreDrawListener。当您以后想要不同的动画时,您是调用 setAdapter 还是使用现有适配器添加/删除项目?
  • 我正在使用现有适配器添加和删除项目。这会导致当前 RecyclerView 中的项目随着 PreDrawListener 中引入的延迟而下移。
  • 你能用你正在尝试的代码发布一个关于它的新问题
【解决方案2】:

我决定使用与 Niko 之前建议的不同的方法。他的方法效果很好并且非常简单,但是在添加和删除项目时会导致一些错误的动画 (as can be seen here)。

所以我决定尝试不同的方法并使用布局动画控制器。这是我用来实现相同结果的代码。

public void initialRVAnimation() {

    AnimationSet set = new AnimationSet(true);

    // Fade in animation
    Animation fadeIn = new AlphaAnimation(0.0f, 1.0f);
    fadeIn.setDuration(400);
    fadeIn.setFillAfter(true);
    set.addAnimation(fadeIn);

    // Slide up animation from bottom of screen
    Animation slideUp = new TranslateAnimation(0, 0, Utils.getScreenHeight(this), 0);
    slideUp.setInterpolator(new DecelerateInterpolator(4.f));
    slideUp.setDuration(400);
    set.addAnimation(slideUp);

    // Set up the animation controller              (second parameter is the delay)
    LayoutAnimationController controller = new LayoutAnimationController(set, 0.2f);
    rv.setLayoutAnimation(controller);

    // Set the adapter
    adapter = new ItemAdapter(data, this);
    recyclerView.setAdapter(adapter);
}

【讨论】:

  • 我正在实施同样的事情,但是当我应用您的答案或接受的答案时,它对我不起作用。对于初始项目看不到动画。都同时出现。你能给我什么建议吗
  • 控制延迟的部分是LayoutAnimationController的第二个参数。确保通过 recyclerView.setLayoutAnimation(controller) 设置布局动画
  • 它对我有用,但在删除项目时我无法使其工作。你这样做了吗?
【解决方案3】:

在 RecyclerView 标记中的 xml 中设置简单的方法(或在上面注释的代码中)

android:layoutAnimation="@anim/slide_left_in_layout_anim"

slide_left_in_layout_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@android:anim/slide_in_left"
    android:delay="10%"
    android:animationOrder="normal"
/>

注意:此动画仅在第一次加载数据时执行,如果您想在添加/删除/移动项目时添加动画,请查看ItemAnimator,我认为this post会帮助您了解一些有用的信息

【讨论】:

    【解决方案4】:

    除了 @Niko 的 对 Kotlin 的回答之外,试试这个解决方案。

    设置适配器后调用它

    rvTop!!.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
                            override fun onPreDraw(): Boolean {
                                rvTop!!.getViewTreeObserver().removeOnPreDrawListener(this);
    
                                for (i in 0 until rvTop!!.getChildCount()) {
                                    var v = rvTop!!.getChildAt(i);
                                    v.setAlpha(0.0f);
                                    v.animate().alpha(1.0f)
                                            .setDuration(300)
                                            .setStartDelay((i * 50).toLong())
                                            .start();
                                }
    
                                return true
                            }
    
    
                        })
    

    【讨论】:

    • 你好快速学习者,你能告诉我你得到什么类型的变量“v”吗?谢谢
    猜你喜欢
    • 2020-06-10
    • 2016-11-01
    • 1970-01-01
    • 2020-06-08
    • 2014-12-30
    • 1970-01-01
    • 2022-01-13
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多