我怎么能动画回收视图项目时出现?

默认的项目动画器只在设置完回收器数据后添加或删除数据时才会动画。

如何实现这一目标?


当前回答

在2019年, 我建议把所有的项目动画放到ItemAnimator中。

让我们从在循环视图中声明动画器开始:

with(view.recycler_view) {
adapter = Adapter()
itemAnimator = CustomAnimator()
}

然后声明自定义动画器,

class CustomAnimator() : DefaultItemAnimator() {

     override fun animateAppearance(
       holder: RecyclerView.ViewHolder,
       preInfo: ItemHolderInfo?,
       postInfo: ItemHolderInfo): Boolean{} // declare  what happens when a item appears on the recycler view

     override fun animatePersistence(
       holder: RecyclerView.ViewHolder,
       preInfo: ItemHolderInfo,
       postInfo: ItemHolderInfo): Boolean {} // declare animation for items that persist in a recycler view even when the items change

}

与上面的类似,还有一个用于消失的animatedisappear,用于添加的animateAdd,用于更改的animateChange和移动的animateMove。

重要的一点是在它们内部调用正确的动画调度器。

其他回答

你可以添加一个android:layoutAnimation="@anim/rv_item_animation"属性到RecyclerView,就像这样:

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"                                        
    android:layoutAnimation="@anim/layout_animation_fall_down"
    />

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

在2019年, 我建议把所有的项目动画放到ItemAnimator中。

让我们从在循环视图中声明动画器开始:

with(view.recycler_view) {
adapter = Adapter()
itemAnimator = CustomAnimator()
}

然后声明自定义动画器,

class CustomAnimator() : DefaultItemAnimator() {

     override fun animateAppearance(
       holder: RecyclerView.ViewHolder,
       preInfo: ItemHolderInfo?,
       postInfo: ItemHolderInfo): Boolean{} // declare  what happens when a item appears on the recycler view

     override fun animatePersistence(
       holder: RecyclerView.ViewHolder,
       preInfo: ItemHolderInfo,
       postInfo: ItemHolderInfo): Boolean {} // declare animation for items that persist in a recycler view even when the items change

}

与上面的类似,还有一个用于消失的animatedisappear,用于添加的animateAdd,用于更改的animateChange和移动的animateMove。

重要的一点是在它们内部调用正确的动画调度器。

我从pbm的答案创建动画,只做了一点修改,使动画只运行一次

换句话说,动画只在你向下滚动时出现

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;
    }
}

并在onBindViewHolder中调用该函数

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

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

// call Animation function
setAnimation(holder.itemView, position);            
}

当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);
}

你也可以用下面的setScaleAnimation()替换setFadeAnimation(),通过从一个点缩放项目来动画它们的外观:

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);
}

上面的代码有一些缺陷,当你滚动RecyclerView项总是褪色或缩放。如果你愿意,你可以添加代码,只允许动画在包含RecyclerView的片段或活动第一次创建时发生(例如,在创建时获得系统时间,只允许动画在第一个FADE_DURATION毫秒)。

当项目被绑定到适配器中时,在recyclerview中进行动画可能不是最好的想法,因为这会导致recyclerview中的项目以不同的速度进行动画。在我的例子中,在recyclerview的末尾的项目动画到他们的位置比顶部的更快,因为顶部的那些有进一步的旅行,所以它看起来不整洁。

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

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

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

步骤1:在你的onCreate方法中设置这个,这样你就可以确保动画只运行一次:

if (savedInstanceState == null) {
    pendingIntroAnimation = true;
}

步骤2:你需要把这段代码放入你想要开始动画的方法中:

if (pendingIntroAnimation) {
    pendingIntroAnimation = false;
    startIntroAnimation();
}

在链接中,作者是动画工具栏图标,所以他把它放在这个方法中:

@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;
}

步骤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();
}

我更倾向于:

我宁愿动画整个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();
}

这将使您的整个recyclerview动画,以便它从屏幕底部飞进来。