如何在RecyclerView项目出现时为其设置动画

Pau*_*ezM 221 android android-layout android-recyclerview

如何出现时,如何为RecyclerView项目设置动画?

默认项目animator仅在设置回收器数据后添加或删除数据时动画.我是新开发的应用程序,并没有任何线索从哪里开始.

任何想法如何实现这一目标?

Mat*_*ree 307

编辑:

根据ItemAnimator文档:

此类定义在对适配器进行更改时对项目进行的动画.

因此,除非您逐个添加项目RecyclerView并在每次迭代时刷新视图,否则我认为不是ItemAnimator您需要的解决方案.

以下是RecyclerView使用CustomAdapter显示项目时的动画:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder>
{
    private Context context;

    // The items to display in your RecyclerView
    private ArrayList<String> items;
    // Allows to remember the last item shown on screen
    private int lastPosition = -1;

    public static class ViewHolder extends RecyclerView.ViewHolder
    {
        TextView text;
        // You need to retrieve the container (ie the root ViewGroup from your custom_item_layout)
        // It's the view that will be animated
        FrameLayout container;

        public ViewHolder(View itemView)
        {
            super(itemView);
            container = (FrameLayout) itemView.findViewById(R.id.item_layout_container);
            text = (TextView) itemView.findViewById(R.id.item_layout_text);
        }
    }

    public CustomAdapter(ArrayList<String> items, Context context)
    {
        this.items = items;
        this.context = context;
    }

    @Override
    public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_item_layout, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position)
    {
        holder.text.setText(items.get(position));

        // Here you apply the animation when the view is bound
        setAnimation(holder.itemView, position);
    }

    /**
     * Here is the key method to apply the animation
     */
    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, android.R.anim.slide_in_left);
            viewToAnimate.startAnimation(animation);
            lastPosition = position;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你的custom_item_layout看起来像这样:

<FrameLayout
    android:id="@+id/item_layout_container"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/item_layout_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

</FrameLayout>
Run Code Online (Sandbox Code Playgroud)

有关CustomAdapters的更多信息RecyclerView,请参阅官方文档中的培训.

快速滚动的问题

使用此方法可能会导致快速滚动问题.在动画发生时,可以重复使用视图.为了避免建议在分离时清除动画.

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder)
    {
        ((CustomViewHolder)holder).clearAnimation();
    }
Run Code Online (Sandbox Code Playgroud)

在CustomViewHolder上:

    public void clearAnimation()
    {
        mRootLayout.clearAnimation();
    }
Run Code Online (Sandbox Code Playgroud)

老答案:

看看Gabriele Mariotti的回购,我很确定你能找到你需要的东西.他为RecyclerView提供了简单的ItemAnimators,例如SlideInItemAnimator或SlideScaleItemAnimator.

  • @GiruBhai覆盖`onViewDetachedFromWindow`并在视图上调用`clearAnimation`.问题是当RecyclerView尝试重用视图时会运行动画. (40认同)
  • 我想知道你是否经历过并且可能在RecyclerView中解决了这些动画的"卡住"效应?我使用类似的ListView代码,无论我滚动多快,我的项目都没有问题,但是使用RecyclerView如果我快速滚动某些项目有时会卡在屏幕上的其他项目之上并且它们不会完全隐藏 - 就像动画在结束前停止了一样.我实际上试图注释掉填充字段的代码部分(试图加快onBindViewHolder方法的执行)所以我只留下了动画的代码 (20认同)
  • @MathieuMaree感谢这个令人惊奇的动画.它看起来很适合慢滚动,但快速滚动recyclelerview项目重叠.你发现这个问题?有任何建议来克服这个问题. (4认同)

pbm*_*pbm 57

Recyclerview当项目第一次出现时,我动画淡出其中,如下面的代码所示.也许这对某人有用.

private final static int FADE_DURATION = 1000; //FADE_DURATION in milliseconds

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

    holder.getTextView().setText("some text");

    // Set the view to fade in
    setFadeAnimation(holder.itemView);            
}

private void setFadeAnimation(View view) {
    AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
    anim.setDuration(FADE_DURATION);
    view.startAnimation(anim);
}
Run Code Online (Sandbox Code Playgroud)

您还可以setFadeAnimation()使用以下内容替换setScaleAnimation()项目的外观,方法是从一个点缩放它们:

private void setScaleAnimation(View view) {
    ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    anim.setDuration(FADE_DURATION);
    view.startAnimation(anim);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码有一些瑕疵,当你滚动RecyclerView项目总是淡出或缩放.如果您希望可以添加代码以仅在RecyclerView首次创建包含该片段或活动的片段或活动时允许动画发生(例如,在创建时获取系统时间并且仅允许第一个FADE_DURATION毫秒的动画).


Bas*_*ANI 23

我从pbm的答案中创建了动画,没有modification让aninmation只运行一次

换句话说 Animation appear with you scroll down only

private int lastPosition = -1;

private void setAnimation(View viewToAnimate, int position) {
    // If the bound view wasn't previously displayed on screen, it's animated
    if (position > lastPosition) {
        ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
        viewToAnimate.startAnimation(anim);
        lastPosition = position;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在onBindViewHolder调用函数

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

holder.getTextView().setText("some text");

// call Animation function
setAnimation(holder.itemView, position);            
}
Run Code Online (Sandbox Code Playgroud)


Pav*_*kov 14

您可以将一个android:layoutAnimation ="@ anim/rv_item_animation"属性添加到R​​ecyclerView,如下所示:

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"                                        
    android:layoutAnimation="@anim/layout_animation_fall_down"
    />
Run Code Online (Sandbox Code Playgroud)

感谢这里出色的文章:https: //proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213


iam*_*ran 14

仅通过XML变得简单

访问要点链接

res / anim / layout_animation.xml

<?xml version="1.0" encoding="utf-8"?>
    <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
        android:animation="@anim/item_animation_fall_down"
        android:animationOrder="normal"
        android:delay="15%" />
Run Code Online (Sandbox Code Playgroud)

res / anim / item_animation_fall_down.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500">

    <translate
        android:fromYDelta="-20%"
        android:toYDelta="0"
        android:interpolator="@android:anim/decelerate_interpolator"
        />

    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:interpolator="@android:anim/decelerate_interpolator"
        />

    <scale
        android:fromXScale="105%"
        android:fromYScale="105%"
        android:toXScale="100%"
        android:toYScale="100%"
        android:pivotX="50%"
        android:pivotY="50%"
        android:interpolator="@android:anim/decelerate_interpolator"
        />

</set>
Run Code Online (Sandbox Code Playgroud)

在布局和recylcerview中使用,例如:

<android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layoutAnimation="@anim/layout_animation"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Run Code Online (Sandbox Code Playgroud)

  • 数据集更改后,您必须调用“recyclerView.scheduleLayoutAnimation()”,否则动画将无法工作。 (32认同)
  • @ArnoldBrown 通过更改动画文件。请参阅:/sf/ask/360611401/ (2认同)
  • 如何在每次打开列表时都执行此操作,因为现在它只是第一次执行此操作。 (2认同)

Ale*_*ola 8

一个好的起点是:https: //github.com/wasabeef/recyclerview-animators/blob/master/animators/src/main/java/jp/wasabeef/recyclerview/adapters/AnimationAdapter.java

你甚至不需要完整的库,那个类就足够了.然后,如果你只是实现你的Adapter类给出这样的动画师:

@Override
protected Animator[] getAnimators(View view) {
    return new Animator[]{
            ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0)
    };
}

@Override
public long getItemId(final int position) {
    return getWrappedAdapter().getItemId(position);
}
Run Code Online (Sandbox Code Playgroud)

你会看到当它们滚动时从底部出现的项目,也避免了快速滚动的问题.


Sim*_*mon 5

当它们绑定在适配器中时,在 recyclerview 中动画项目可能不是最好的主意,因为这可能导致 recyclerview 中的项目以不同的速度动画。在我的情况下,recyclerview 末尾的项目比顶部的项目更快地动画到他们的位置,因为顶部的项目需要走得更远,所以它看起来不整洁。

我用来将每个项目动画化到 recyclerview 的原始代码可以在这里找到:

http://frogermcs.github.io/Instagram-with-Material-Design-concept-is-getting-real/

但我会复制并粘贴代码,以防链接中断。

第 1在您的 onCreate 方法中设置它,以确保动画只运行一次:

if (savedInstanceState == null) {
    pendingIntroAnimation = true;
}
Run Code Online (Sandbox Code Playgroud)

第 2 步:您需要将此代码放入要启动动画的方法中:

if (pendingIntroAnimation) {
    pendingIntroAnimation = false;
    startIntroAnimation();
}
Run Code Online (Sandbox Code Playgroud)

在链接中,作者正在为工具栏图标设置动画,因此他将其放入此方法中:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    inboxMenuItem = menu.findItem(R.id.action_inbox);
    inboxMenuItem.setActionView(R.layout.menu_item_view);
    if (pendingIntroAnimation) {
        pendingIntroAnimation = false;
        startIntroAnimation();
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

第 3现在编写 startIntroAnimation() 的逻辑:

private static final int ANIM_DURATION_TOOLBAR = 300;

private void startIntroAnimation() {
    btnCreate.setTranslationY(2 * getResources().getDimensionPixelOffset(R.dimen.btn_fab_size));

    int actionbarSize = Utils.dpToPx(56);
    toolbar.setTranslationY(-actionbarSize);
    ivLogo.setTranslationY(-actionbarSize);
    inboxMenuItem.getActionView().setTranslationY(-actionbarSize);

    toolbar.animate()
            .translationY(0)
            .setDuration(ANIM_DURATION_TOOLBAR)
            .setStartDelay(300);
    ivLogo.animate()
            .translationY(0)
            .setDuration(ANIM_DURATION_TOOLBAR)
            .setStartDelay(400);
    inboxMenuItem.getActionView().animate()
            .translationY(0)
            .setDuration(ANIM_DURATION_TOOLBAR)
            .setStartDelay(500)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    startContentAnimation();
                }
            })
            .start();
}
Run Code Online (Sandbox Code Playgroud)

我的首选替代方案:

我宁愿动画整个 recyclerview 而不是 recyclerview 中的项目。

第 1 步和第 2 步保持不变。

在第 3 步中,一旦您的 API 调用返回您的数据,我就会开始动画。

private void startIntroAnimation() {
    recyclerview.setTranslationY(latestPostRecyclerview.getHeight());
    recyclerview.setAlpha(0f);
    recyclerview.animate()
            .translationY(0)
            .setDuration(400)
            .alpha(1f)
            .setInterpolator(new AccelerateDecelerateInterpolator())
            .start();
}
Run Code Online (Sandbox Code Playgroud)

这将使您的整个 recyclerview 动画化,使其从屏幕底部飞入。


Md.*_*lam 5

将此方法创建到您的recyclerview适配器中

private void setZoomInAnimation(View view) {
        Animation zoomIn = AnimationUtils.loadAnimation(context, R.anim.zoomin);// animation file 
        view.startAnimation(zoomIn);
    }
Run Code Online (Sandbox Code Playgroud)

最后在onBindViewHolder添加这行代码

setZoomInAnimation(holder.itemView);