如何为新项目添加RecyclerView滑入动画

4

我有一个RecyclerView,并在索引0处向mCommentArrayList添加项目。我正在尝试创建一个滑入动画,当新项目(CardViews)添加到RecyclerView时,它们会出现在视图的顶部。

我知道有可以使用的库,甚至已经探索过https://github.com/wasabeef/recyclerview-animators。然而,文档有限,我不确定采取什么方法。

请注意,我将所有新项目添加到我的mCommentArrayList中的index 0,以便它们出现在视图的顶部。我知道适配器中还有一些工作要做,特别是onBindViewHolder(),但我不知道具体要放什么以激活动画。

这是我第一次调用Firebase查找数据以填充RecyclerView的地方:

    mUpdateRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            setImage(dataSnapshot);
            setQuestion(dataSnapshot);
            createInitialCommentIDArray(dataSnapshot);
            mNumberOfCommentsAtPoll = (int) dataSnapshot.child(COMMENTS_LABEL).getChildrenCount();
            for (int i = 0; i < mNumberOfCommentsAtPoll; i++) {
                String commentID = (String) dataSnapshot.child(COMMENTS_LABEL).child(mCommentIDArrayList.get(i)).child("COMMENT").getValue();
                Log.v("COMMENT_ID", "The comment ID is " + commentID);
                String userID = (String) dataSnapshot.child(COMMENTS_LABEL).child(mCommentIDArrayList.get(i)).child("USER_ID").getValue();
                Log.v("USER_ID", "The user ID is " + userID);
                mCommentArrayList.add(0, new Comments(mUserAvatar, userID, commentID));
                mCommentAdapter.notifyDataSetChanged();
            }

        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });

对于 Firebase 数据更改后的后续调用:

@Override
protected void onStart() {
    super.onStart();
    mUpdateComments = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            mNumberOfCommentsAtPoll = (int) dataSnapshot.getChildrenCount();
            for (DataSnapshot x : dataSnapshot.child(COMMENTS_LABEL).getChildren()) {
                Log.v("DATA_SNAPSHOT", x.toString());
                if (mCommentIDArrayList.contains(x.getKey())) {
                    Log.v("Comment_Already_Added", x.getKey());
                } else {
                    Log.v("Child_Added_Called", "Child Added Called");
                    mCommentIDArrayList.add(x.getKey());
                    String commentID = (String) dataSnapshot.child(COMMENTS_LABEL).child(x.getKey()).child("COMMENT").getValue();
                    Log.v("New_Comment", "The new comment is " + commentID);
                    String userID = (String) dataSnapshot.child(COMMENTS_LABEL).child(x.getKey()).child("USER_ID").getValue();
                    Log.v("New_User_ID", "The new userID is " + userID);
                    mCommentArrayList.add(0, new Comments(mUserAvatar, userID, commentID));
                    mPollCommentsList.getAdapter().notifyItemInserted(0);
                }
            }
        }
3个回答

8
使用你提到的库(https://github.com/wasabeef/recyclerview-animators),很容易向你的RecyclerView添加SlideInAnimator。只需使用以下代码将Animator设置给你的RecyclerView(选择一个):
    recyclerView.setItemAnimator(new SlideInDownAnimator());
    recyclerView.setItemAnimator(new SlideInRightAnimator());
    recyclerView.setItemAnimator(new SlideInLeftAnimator());
    recyclerView.setItemAnimator(new SlideInUpAnimator());

一旦完成此操作,您可以通过调用notifyItemInserted(position)notifyItemRangeInserted(positionStart, itemCount)来触发动画。这些调用将触发Animator,调用notifyDatasetChanged() 不会触发动画。

触发插入动画:

    recyclerView.getAdapter().notifyItemInserted(position);
    recyclerView.getAdapter().notifyItemRangeInserted(positionStart, itemCount);

谢谢,我会尝试一下,所以在调用动画时,我完全消除了使用notifyDataSetChanged()的方法? - tccpg288
是的。如果你想让动画正常工作,不要依赖调用notifyDataSetChanged()方法,因为RecyclerView默认行为是在该方法中不触发动画开始。 - Jeffalee
它实际上没有起作用。视图中根本没有任何东西显示。我删除了notifyDataSetChanged()并添加了notifyItemInserted()方法。我可以创建一个新的SO帖子并展示代码吗? - tccpg288

6
希望这段代码能对你有所帮助!
创建一个动画文件animation_from_right.xml。
<?xml version="1.0" encoding="utf-8"?>

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

<translate
android:interpolator="@android:anim/decelerate_interpolator"
android:fromXDelta="100%p"
android:toXDelta="0"
/>

<alpha
android:fromAlpha="0.5"
android:toAlpha="1"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
/>

</set>

在Activity中
Animation animation = AnimationUtils.loadAnimation(mActivity, R.anim.animation_from_right);
        holder.itemView.startAnimation(animation);

在您的适配器中的onBindViewHolder方法中使用上述代码。


2
Saurabh,这是简单而完美的解决方案。+1 - Harin Kaklotar

1
最好的方法是在onBindViewHolder方法中进行recyclerview的动画处理。
下面是如何实现:
在适配器类中创建一个名为lastAnimatedPosition的字段变量。
private int lastAnimatedPosition = -1;

在onbindviewholder中 -
 @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Comments comment = mDataSet.get(position);
        holder.userComment.setText(comment.getUserComment());
        holder.userID.setText("User " + position);
if (position > lastAnimatedPosition) {
      lastAnimatedPosition = position;
      Animation animation = AnimationUtils.loadAnimation(context, R.anim.my_anim_set);
      animation.setInterpolator(new AccelerateDecelerateInterpolator());
      ((ViewHolder) holder).container.setAnimation(animation);
      animation.start();
    }
    }

下一步是在您的视图持有者类中进行一些微调-
public class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        protected ImageView userAvatar;
        protected TextView userID;
        protected TextView userComment;
        **protected View container;**


        public ViewHolder(View v) {
            super(v);
            **container = v;**
            userAvatar = (ImageView) v.findViewById(R.id.profile_image);
            userID = (TextView) v.findViewById(R.id.user_ID);
            userComment = (TextView) v.findViewById(R.id.user_comment_textview);
        }

        **public void clearAnimation() {
          container.clearAnimation();
        }**
    }

最后,只需要覆盖onViewDetachedFromWindow方法即可-
@Override
  public void onViewDetachedFromWindow(final ViewHolder holder) {
    holder.clearAnimation();
  }

更新

由于要进行动画的元素位于0号位置,将if (position > lastAnimatedPosition)代码段替换为-

if (position == 0) {
      lastAnimatedPosition = position;
      Animation animation = AnimationUtils.loadAnimation(context, R.anim.my_anim_set);
      animation.setInterpolator(new AccelerateDecelerateInterpolator());
      ((ViewHolder) holder).container.setAnimation(animation);
      animation.start();
    }

非常感谢,我会尝试一下。请记住,每个新项目都是在“0”索引处添加的。不确定如何在onBindViewHolder方法中使用它,因为我注意到所有视图都会滑动,而不仅仅是最新的... - tccpg288
你是对的...这将使所有元素滑动。关于“0”索引问题,我已经更新了我的答案。 - Vaibhav Sharma
非常感谢,我会让你知道的。onViewDetachedFromWindow()中的override实际上是做什么的?我有点困惑它的目的/功能。 - tccpg288
这告诉代码视图不再连接到窗口。我使用这个来告诉代码视图已经不再连接,因此应该停止动画。如果我们不在这里清除动画,当我们快速滚动时会出现很多UI故障。 - Vaibhav Sharma
明白了,非常感谢。 - tccpg288

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接