【问题标题】:How To Add RecyclerView Slide In Animation for New Item如何在新项目的动画中添加 RecyclerView 幻灯片
【发布时间】:2016-09-23 12:09:37
【问题描述】:

我有一个 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);
                }
            }
        }

【问题讨论】:

    标签: java android xml android-layout android-recyclerview


    【解决方案1】:

    希望这段代码对你有帮助!

    创建一个动画文件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>
    

    在活动中

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

    在 onBindViewHolder 上的 Adapter 中使用上述代码

    【讨论】:

    • Saurabh 这是简单而完美的解决方案。 +1
    【解决方案2】:

    为 recyclerview 设置动画的最佳方式是在 onbindviewholder method 中进行。

    这是怎么做的-

    在适配器类中创建一个字段变量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();
        }
        }
    

    接下来对你的viewholder类进行一些调整-

    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 &gt; lastAnimatedPosition) sn-p 替换为 -

    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 方法一起使用,因为我注意到所有视图都滑入,而不仅仅是最新的......
    • 你是对的......这将使所有元素滑入。对于“0”索引问题,我已经更新了我的答案。
    • 非常感谢,我会告诉你的。对 onViewDetachedFromWindow() 的覆盖实际上做了什么?我对其目的/功能有点困惑。
    • 这告诉视图不再附加到窗口。我用它来告诉代码视图不再附加,因此它应该停止动画。如果我们不清除这里的动画,我们在快速滚动时会出现很多 UI 故障。
    • 知道了,非常感谢。
    【解决方案3】:

    使用您所谈论的库 (https://github.com/wasabeef/recyclerview-animators),很容易将 SlideInAnimator 添加到您的 RecyclerView。只需使用以下代码将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() 了?
    • 是的。如果你想让你的动画工作,不要依赖于调用 notifyDataSetChanged();由于它是 RecyclerView 的默认行为,因此在此方法中不会触发动画。
    • 它实际上没有用。视图中什么都没有出现。我删除了 notifyDataSetChanged() 并添加了 notifyItemInserted() 方法。我可以创建一个新的 SO 帖子并显示代码吗?
    猜你喜欢
    • 1970-01-01
    • 2019-11-16
    • 2020-10-31
    • 1970-01-01
    • 2022-08-21
    • 1970-01-01
    • 2021-04-24
    • 2018-02-20
    • 1970-01-01
    相关资源
    最近更新 更多