RecyclerView动画源码浅析

RecyclerView动画源码浅析
adapter.notifyItemRemoved(1)会回调到 RecyclerViewDataObserver:

adapter.notifyItemRemoved           RecyclerViewDataObserver

onItemRangeRemoved

triggerUpdateProcessor

mAdapterUpdateDuringMeasure

consumePendingUpdateOperations
dispatchLayout
dispatchLayoutStep1

processAdapterUpdatesAndSetAnimationFlags
preProcess

applyRemove
postponeAndUpdateViewHolders
offsetPositionsForRemovingLaidOutOrNewView
offsetPositionRecordsForRemove
flagRemovedAndOffsetPosition
setFrom
ItemHolderInfo ViewHolder mViewInfoStore  mLayoutHolderMap    保存动画前View的现场 


       if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
                ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
            }
            
            
              final Runnable mUpdateChildViewsRunnable = new Runnable() {
        @Override
        public void run() {
        
        
                    consumePendingUpdateOperations();
                    
                             dispatchLayout();
                             
                                dispatchLayoutStep1();


  @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeRemoved(positionStart, itemCount)) {
                triggerUpdateProcessor();
            }
        }


 mPendingUpdates.add(obtainUpdateOp(UpdateOp.REMOVE, positionStart, itemCount, null));

    final ArrayList<UpdateOp> mPendingUpdates = new ArrayList<UpdateOp>();
    
    triggerUpdateProcessor()调用了requestLayout, 即触发了RecyclerView的重新布局。
    
    void triggerUpdateProcessor() {
            if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
                ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
            } else {
                mAdapterUpdateDuringMeasure = true;
                requestLayout();
            }
        }
        
            void dispatchLayout() {
               dispatchLayoutStep1();        
               processAdapterUpdatesAndSetAnimationFlags();
               
                     mAdapterHelper.preProcess();
                     
                      case UpdateOp.REMOVE:
                    applyRemove(op);
                    break;
            postponeAndUpdateViewHolders(op);

      case UpdateOp.REMOVE:
                mCallback.offsetPositionsForRemovingLaidOutOrNewView(op.positionStart,
                        op.itemCount);
                break;    

                

 void offsetPositionRecordsForRemove(int positionStart, int itemCount,
            boolean applyToPreLayout) {
            
            
                  holder.flagRemovedAndOffsetPosition(positionStart - 1, -itemCount,
                            applyToPreLayout);
                    mState.mStructureChanged = true;
                    
                    flagRemovedAndOffsetPosition
            
            
            offsetPositionRecordsForRemove方法:主要是把当前显示在界面上的ViewHolder的位置做对应的改变,即如果item位于删除的item之后,那么它的位置应该减一,比如原来的位置是3现在变成了2。

RecyclerView                
                        @Override
            public void offsetPositionsForRemovingLaidOutOrNewView(
                    int positionStart, int itemCount) {
                offsetPositionRecordsForRemove(positionStart, itemCount, false);
                mItemsAddedOrRemoved = true;
            }

                    

    
     final ItemHolderInfo animationInfo
  @NonNull
            public ItemHolderInfo setFrom(@NonNull RecyclerView.ViewHolder holder,
                    @AdapterChanges int flags) {
                final View view = holder.itemView;
                this.left = view.getLeft();
                this.top = view.getTop();
                this.right = view.getRight();
                this.bottom = view.getBottom();
                return this;
            }


                    mViewInfoStore.addToPreLayout(holder, animationInfo);        
                    
                static Pools.Pool<InfoRecord> sPool = new Pools.SimplePool<>(20);            
                    
                    
                即把holder 和 info保存到 mLayoutHolderMap 中。可以理解为它是用来保存动画执行前当前界面ViewHolder的信息一个集合。


        @VisibleForTesting
    final ArrayMap<RecyclerView.ViewHolder, InfoRecord> mLayoutHolderMap = new ArrayMap<>();            
                    
    
其实这些操作可以简单的理解为保存动画前View的现场 


dispatchLayoutStep2

   // Step 2: Run layout
        mState.mInPreLayout = false;
        mLayout.onLayoutChildren(mRecycler, mState);
   fill(recycler, mLayoutState, state, false);

  layoutChunk(recycler, state, layoutState, layoutChunkResult);

   View view = layoutState.next(recycler);

       final View view = recycler.getViewForPosition(mCurrentPosition);

  return tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView;

dispatchLayoutStep3(执行删除动画)

    @VisibleForTesting
    final LongSparseArray<RecyclerView.ViewHolder> mOldChangedHolders = new LongSparseArray<>()

            // Step 4: Process view info lists and trigger animations
            mViewInfoStore.process(mViewInfoProcessCallback);


        private final ViewInfoStore.ProcessCallback mViewInfoProcessCallback =
                    
                    
                        public void processDisappeared(ViewHolder viewHolder, @NonNull ItemHolderInfo info,
                        @Nullable ItemHolderInfo postInfo) {
                    mRecycler.unscrapView(viewHolder);
                    animateDisappearance(viewHolder, info, postInfo);
                    
                    
                    
                  callback.processDisappeared(viewHolder, record.preInfo, record.postInfo);
                }    
                    
                    
                    
                    
                                        animateDisappearance(viewHolder, info, postInfo);
                    
                    
                    
                    
            addAnimatingView(holder);                
                    
               // re-attach
            mChildHelper.attachViewToParent(view, -1, view.getLayoutParams(), true);        
                    
                        if (mItemAnimator.animateDisappearance(holder, preLayoutInfo, postLayoutInfo)) {    
                    
                  return animateMove(viewHolder, oldLeft, oldTop, newLeft, newTop);        
                    
                    
           if (deltaX != 0) {
            view.setTranslationX(-deltaX);
        }
        if (deltaY != 0) {
            view.setTranslationY(-deltaY);
        }
        mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));            
                    
            private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();            
                    
        将未被删除的Item的移动动画放入到mPendingMoves待执行队列

       postAnimationRunner();


rivate Runnable mItemAnimatorRunner = new Runnable() {
        @Override


     mItemAnimator.runPendingAnimations();


   animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
                                moveInfo.toX, moveInfo.toY);

animateRemoveImpl 把这个被Remove的Item做一个透明度由(1~0)的动画
animateMoveImpl把它们的TranslationX和TranslationY移动到0的位置。

        
                    
                    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值