美文网首页安卓
RecyclerView<第十六篇>:条目动画之自定义Defau

RecyclerView<第十六篇>:条目动画之自定义Defau

作者: NoBugException | 来源:发表于2019-08-15 11:22 被阅读0次

    为了让RecyclerView更加用户友好,可以给条目添加动画,RecyclerView可以设置条目动画

    设置条目动画的代码是:

    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    

    可以给RecyclerView设置一个默认的动画,使用默认动画的话可以给条目设置动画时间

        DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator();
        defaultItemAnimator.setRemoveDuration(200);
        defaultItemAnimator.setAddDuration(200);
        defaultItemAnimator.setMoveDuration(200);
        defaultItemAnimator.setChangeDuration(200);
        mRecyclerView.setItemAnimator(defaultItemAnimator);
    

    另外,还可以自定义一个动画,这样就需要深入研究DefaultItemAnimator类了。

    DefaultItemAnimator的最终父类是ItemAnimator,该类是RecyclerView的内部抽象类,根据它抽象的特性,我们可以自定义ItemAnimator,当然,如果这样的话就比较复杂了,因此,就自定义DefaultItemAnimator了。

    public class MyCustomItemAnimator extends DefaultItemAnimator {
    
        @Override
        public boolean animateRemove(RecyclerView.ViewHolder holder) {
            //删除条目动画实现
            return super.animateRemove(holder);
        }
    
        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            //添加条目动画实现
            return super.animateAdd(holder);
        }
    
        @Override
        public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            //移动条目动画实现
            return super.animateMove(holder, fromX, fromY, toX, toY);
        }
    
        @Override
        public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
            //改变条目动画实现
            return super.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY);
        }
    }
    

    如上代码,动画的实现主要体现在animateRemoveanimateAddanimateMoveanimateChange这四个方法。

    在不做修改的情况下,条目动画都是默认的,想要学会自定义动画,那么首先需要研究下DefaultItemAnimator类的源码。

    研究源码后发现,当触发添加条目动作时会执行

    public boolean animateAdd(ViewHolder holder) {
        this.resetAnimation(holder);
        holder.itemView.setAlpha(0.0F);
        this.mPendingAdditions.add(holder);
        return true;
    }
    

    当触发条目移动动作时执行

    public boolean animateMove(ViewHolder holder, int fromX, int fromY, int toX, int toY) {
        View view = holder.itemView;
        fromX += (int)holder.itemView.getTranslationX();
        fromY += (int)holder.itemView.getTranslationY();
        this.resetAnimation(holder);
        int deltaX = toX - fromX;
        int deltaY = toY - fromY;
        if (deltaX == 0 && deltaY == 0) {
            this.dispatchMoveFinished(holder);
            return false;
        } else {
            if (deltaX != 0) {
                view.setTranslationX((float)(-deltaX));
            }
    
            if (deltaY != 0) {
                view.setTranslationY((float)(-deltaY));
            }
    
            this.mPendingMoves.add(new DefaultItemAnimator.MoveInfo(holder, fromX, fromY, toX, toY));
            return true;
        }
    }
    

    当触发条目删除时执行

    public boolean animateRemove(ViewHolder holder) {
        this.resetAnimation(holder);
        this.mPendingRemovals.add(holder);
        return true;
    }
    

    当条目状态改变时

    public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
        if (oldHolder == newHolder) {
            return this.animateMove(oldHolder, fromX, fromY, toX, toY);
        } else {
            float prevTranslationX = oldHolder.itemView.getTranslationX();
            float prevTranslationY = oldHolder.itemView.getTranslationY();
            float prevAlpha = oldHolder.itemView.getAlpha();
            this.resetAnimation(oldHolder);
            int deltaX = (int)((float)(toX - fromX) - prevTranslationX);
            int deltaY = (int)((float)(toY - fromY) - prevTranslationY);
            oldHolder.itemView.setTranslationX(prevTranslationX);
            oldHolder.itemView.setTranslationY(prevTranslationY);
            oldHolder.itemView.setAlpha(prevAlpha);
            if (newHolder != null) {
                this.resetAnimation(newHolder);
                newHolder.itemView.setTranslationX((float)(-deltaX));
                newHolder.itemView.setTranslationY((float)(-deltaY));
                newHolder.itemView.setAlpha(0.0F);
            }
    
            this.mPendingChanges.add(new DefaultItemAnimator.ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
            return true;
        }
    }
    

    以上四个方法并不是为了执行动画,而是初始化动画的准备工作,它们的作用大致有两个:
    【一】 设置ViewHolder的初始状态,比如:

    newHolder.itemView.setAlpha(0.0F);
    

    【二】 存储将要执行动画的ViewHolder,比如:

    //存储将要执行动画的ViewHolder(移除Item)
    this.mPendingRemovals.add(holder);
    
    //存储将要执行动画的ViewHolder(Item状态改变)
    this.mPendingChanges.add(new DefaultItemAnimator.ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
    
    //存储将要执行动画的ViewHolder(位移Item)
    this.mPendingMoves.add(new DefaultItemAnimator.MoveInfo(holder, fromX, fromY, toX, toY));
    
    //存储将要执行动画的ViewHolder(新增Item)
    this.mPendingAdditions.add(holder);
    

    当一切准备工作做好之后,开始执行runPendingAnimations方法

    public void runPendingAnimations() {
        boolean removalsPending = !this.mPendingRemovals.isEmpty();
        boolean movesPending = !this.mPendingMoves.isEmpty();
        boolean changesPending = !this.mPendingChanges.isEmpty();
        boolean additionsPending = !this.mPendingAdditions.isEmpty();
        if (removalsPending || movesPending || additionsPending || changesPending) {
            Iterator var5 = this.mPendingRemovals.iterator();
    
            while(var5.hasNext()) {
                ViewHolder holder = (ViewHolder)var5.next();
                this.animateRemoveImpl(holder);
            }
    
            this.mPendingRemovals.clear();
            final ArrayList additions;
            Runnable adder;
            if (movesPending) {
                additions = new ArrayList();
                additions.addAll(this.mPendingMoves);
                this.mMovesList.add(additions);
                this.mPendingMoves.clear();
                adder = new Runnable() {
                    public void run() {
                        Iterator var1 = additions.iterator();
    
                        while(var1.hasNext()) {
                            DefaultItemAnimator.MoveInfo moveInfo = (DefaultItemAnimator.MoveInfo)var1.next();
                            DefaultItemAnimator.this.animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, moveInfo.toX, moveInfo.toY);
                        }
    
                        additions.clear();
                        DefaultItemAnimator.this.mMovesList.remove(additions);
                    }
                };
                if (removalsPending) {
                    View view = ((DefaultItemAnimator.MoveInfo)additions.get(0)).holder.itemView;
                    ViewCompat.postOnAnimationDelayed(view, adder, this.getRemoveDuration());
                } else {
                    adder.run();
                }
            }
    
            if (changesPending) {
                additions = new ArrayList();
                additions.addAll(this.mPendingChanges);
                this.mChangesList.add(additions);
                this.mPendingChanges.clear();
                adder = new Runnable() {
                    public void run() {
                        Iterator var1 = additions.iterator();
    
                        while(var1.hasNext()) {
                            DefaultItemAnimator.ChangeInfo change = (DefaultItemAnimator.ChangeInfo)var1.next();
                            DefaultItemAnimator.this.animateChangeImpl(change);
                        }
    
                        additions.clear();
                        DefaultItemAnimator.this.mChangesList.remove(additions);
                    }
                };
                if (removalsPending) {
                    ViewHolder holder = ((DefaultItemAnimator.ChangeInfo)additions.get(0)).oldHolder;
                    ViewCompat.postOnAnimationDelayed(holder.itemView, adder, this.getRemoveDuration());
                } else {
                    adder.run();
                }
            }
    
            if (additionsPending) {
                additions = new ArrayList();
                additions.addAll(this.mPendingAdditions);
                this.mAdditionsList.add(additions);
                this.mPendingAdditions.clear();
                adder = new Runnable() {
                    public void run() {
                        Iterator var1 = additions.iterator();
    
                        while(var1.hasNext()) {
                            ViewHolder holder = (ViewHolder)var1.next();
                            DefaultItemAnimator.this.animateAddImpl(holder);
                        }
    
                        additions.clear();
                        DefaultItemAnimator.this.mAdditionsList.remove(additions);
                    }
                };
                if (!removalsPending && !movesPending && !changesPending) {
                    adder.run();
                } else {
                    long removeDuration = removalsPending ? this.getRemoveDuration() : 0L;
                    long moveDuration = movesPending ? this.getMoveDuration() : 0L;
                    long changeDuration = changesPending ? this.getChangeDuration() : 0L;
                    long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
                    View view = ((ViewHolder)additions.get(0)).itemView;
                    ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
                }
            }
    
        }
    }
    

    runPendingAnimations方法中,有执行四种动画的方法,分别是:

    【animateRemoveImpl】 删除动画
    【animateChangeImpl】 状态改变动画
    【animateAddImpl】 添加条目动画
    【animateMoveImpl】 条目位移动画

    所以,可以断定,runPendingAnimations方法的作用是执行所有集合中的动画。

    RecyclerView条目动画执行流程

    从源码分析,RecyclerView条目动画执行过程是:(很重要)

    animateAdd-->runPendingAnimations-->animateAddImpl
    animateMove-->runPendingAnimations-->animateMoveImpl
    animateRemove-->runPendingAnimations-->animateRemoveImpl
    animateChange-->runPendingAnimations-->animateChangeImpl

    前面源码看不懂不要紧,但是条目动画基本执行流程必须要清楚,因为接下来开始一步一步的手写自定义DefaultItemAnimator。

    【第一步】 新建DefaultItemAnimator类,继承DefaultItemAnimator

    我们看一下DefaultItemAnimator类,它的回调方法都是从父类DefaultItemAnimator重写过来的

    public class MyCustomItemAnimator extends DefaultItemAnimator {
    
        @Override
        public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull List<Object> payloads) {
            return super.canReuseUpdatedViewHolder(viewHolder, payloads);
        }
    
        @Override
        public void runPendingAnimations() {
            super.runPendingAnimations();
        }
    
        @Override
        public boolean animateRemove(RecyclerView.ViewHolder holder) {
            return super.animateRemove(holder);
        }
    
        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            return super.animateAdd(holder);
        }
    
        @Override
        public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            return super.animateMove(holder, fromX, fromY, toX, toY);
        }
    
        @Override
        public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
            return super.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY);
        }
    
        @Override
        public void endAnimation(RecyclerView.ViewHolder item) {
            super.endAnimation(item);
        }
    
        @Override
        public boolean isRunning() {
            return super.isRunning();
        }
    
        @Override
        public void endAnimations() {
            super.endAnimations();
        }
        
    }
    

    那些方法有什么用呢?(重点)

    • canReuseUpdatedViewHolder

    RecyclerView的复用机制是否可用,这里一般默认即可,或者将这个返回值改成true,也就是说,默认复用机制可用。然而,决定RecyclerView是否可以复用不仅仅是根据canReuseUpdatedViewHolder方法的返回值,而且还需要看Adapter中的getItemViewType方法的返回值。

    也就是说,当canReuseUpdatedViewHolder的返回值为true并且多个ViewHolder为同一个类型,说明可复用。

    @Override
    public int getItemViewType(int position) {
        //所有ViewHolder类型都是0,所有都可复用
        return 0;
    }
    
    @Override
    public int getItemViewType(int position) {
        //所有ViewHolder类型都是不一样,所有都不可复用
        return position;
    }
    
    @Override
    public int getItemViewType(int position) {
        //ViewHolder类型为0的可以相互复用,ViewHolder类型为1的可以相互复用,不同类型的不可相互复用
        if(a){
            return 0;
        }else{
            return 1;
        }
    }
    
    • animateAdd

    这个方法的作用是存储即将被添加的ViewHolder。
    这个方法的执行是最为频繁的了。
    当RecyclerView删除某一项时,删除项之后的项都要被重新添加;
    当RecyclerView新增某项时,新增项之后的项都要被重新添加;
    当RecyclerView指定两个项相互对换位移时,这两项需要被重新添加;

    • animateRemove

    这个方法的作用是存储即将被删除的ViewHolder。
    当删除某项时,会执行这个方法。

    • animateMove

    这个方法的作用是存储即将被位移的ViewHolder。
    当新增项、删除项、项状态改变时都会执行到这个回调。
    需要说明的是,当交换某两项位置时,这里只会触发animateAdd方法,而不会执行animateMove方法。

    • animateChange

    这个方法的作用是存储即将状态被改变的ViewHolder。
    当项状态改变时,执行animateChange方法。

    • isRunning

    判断当前动画是否正在执行。

    • runPendingAnimations

    这个方法才是最终执行动画的地方,animateAdd、animateRemove、animateMove、animateChange这四个方法只是将将要执行动画的ViewHolder保存到集合里面,最终这四个集合会在runPendingAnimations方法里遍历,将所有的ViewHolder执行动画。

    • endAnimation

    结束动画时调用。

    • endAnimations

    结束动画时调用。

    【第二步】 条目被添加、删除、位移、改变时会执行到哪些方法?

    • 添加项
    adapter.notifyItemInserted(position);
    

    当在指定位置插入某项时,会执行animateMove和animateAdd方法存储ViewHolder,最后执行runPendingAnimations方法执行动画。

    • 删除项
    adapter.notifyItemRemoved(position);
    

    当删除某项时,会执行animateRemove、animateAdd、animateMove这三个方法存储ViewHolder,最后执行runPendingAnimations方法执行动画。

    • 位移项
    adapter.notifyItemMoved(position, position + 1);
    

    当两个项互相交换位置时,执行animateAdd方法存储ViewHolder,最后执行runPendingAnimations方法执行动画。

    • 项状态改变
    adapter.notifyItemChanged(position);
    

    当项状态改变时,执行animateChange和animateMove方法存储ViewHolder,最后执行runPendingAnimations方法执行动画。

    【第三步】 将DefaultItemAnimator类中的基本实现拷贝到MyCustomItemAnimator方法中,报错的地方可以自行修改。

    以下贴出我整理之后的代码

    public class MyCustomItemAnimator extends DefaultItemAnimator {
    
        //用于存储将要移动的MoveInfo对象
        private ArrayList<MyCustomItemAnimator.MoveInfo> mPendingMoves = new ArrayList();
        //MoveInfo的临时存储集合
        private ArrayList<ArrayList<MyCustomItemAnimator.MoveInfo>> mMovesList = new ArrayList();
        //用于存储正在执行移动动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList();
        //用于存储将要被添加的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList();
        //存储被添加的ViewHolder的临时集合
        private ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList();
        //用于存储正在执行添加动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList();
        //用于存储将要删除的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList();
        //用于存储正在执行删除动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList();
        //用于存储将要改变的ViewHolder
        private ArrayList<MyCustomItemAnimator.ChangeInfo> mPendingChanges = new ArrayList();
        //存储被改变的ViewHolder的临时集合
        private ArrayList<ArrayList<MyCustomItemAnimator.ChangeInfo>> mChangesList = new ArrayList();
        //用于存储正在执行改变动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList();
    
        //定义一个插值器:先向相反方向改变,再加速播放,会超出目标值
        private AnticipateOvershootInterpolator accelerateDecelerateInterpolator;
    
        @Override
        public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
            return true;
        }
    
    
        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            //添加条目动画实现
    
            //开始重置动画
            holder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(holder);
    
            //让被添加的条目初始完全透明
            holder.itemView.setAlpha(0.0f);
    
            //把即将被添加的ViewHolder暂时缓存到mPendingAdditions中
            mPendingAdditions.add(holder);
            return true;
        }
    
    
        @Override
        public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            //移动条目动画实现
    
            View view = holder.itemView;
            fromX += (int)holder.itemView.getTranslationX();
            fromY += (int)holder.itemView.getTranslationY();
    
            //开始重置动画
            holder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(holder);
    
            int deltaX = toX - fromX;
            int deltaY = toY - fromY;
            if (deltaX == 0 && deltaY == 0) {
                dispatchMoveFinished(holder);
                return false;
            } else {
                if (deltaX != 0) {
                    view.setTranslationX((float)(-deltaX));
                }
    
                if (deltaY != 0) {
                    view.setTranslationY((float)(-deltaY));
                }
    
                mPendingMoves.add(new MyCustomItemAnimator.MoveInfo(holder, fromX, fromY, toX, toY));
                return true;
            }
        }
    
        @Override
        public boolean animateRemove(RecyclerView.ViewHolder holder) {
            //删除条目动画实现
    
    
            //开始重置动画
            holder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(holder);
    
            //把将要执行删除动画的ViewHolder放入mPendingRemovals集合
            mPendingRemovals.add(holder);
            return true;
        }
    
        @Override
        public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
            //改变条目动画实现
    
    
            if (oldHolder == newHolder) {
                return this.animateMove(oldHolder, fromX, fromY, toX, toY);
            } else {
                float prevTranslationX = oldHolder.itemView.getTranslationX();
                float prevTranslationY = oldHolder.itemView.getTranslationY();
                float prevAlpha = oldHolder.itemView.getAlpha();
    
                //开始重置动画
                oldHolder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
                endAnimation(oldHolder);
    
                int deltaX = (int)((float)(toX - fromX) - prevTranslationX);
                int deltaY = (int)((float)(toY - fromY) - prevTranslationY);
                oldHolder.itemView.setTranslationX(prevTranslationX);
                oldHolder.itemView.setTranslationY(prevTranslationY);
                oldHolder.itemView.setAlpha(prevAlpha);
                if (newHolder != null) {
    
                    //开始重置动画
                    newHolder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
                    endAnimation(newHolder);
    
                    newHolder.itemView.setTranslationX((float)(-deltaX));
                    newHolder.itemView.setTranslationY((float)(-deltaY));
                    newHolder.itemView.setAlpha(0.0F);
                }
    
                this.mPendingChanges.add(new MyCustomItemAnimator.ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
                return true;
            }
        }
    
        @Override
        public void runPendingAnimations() {
            boolean removalsPending = !mPendingRemovals.isEmpty();
            boolean movesPending = !mPendingMoves.isEmpty();
            boolean changesPending = !mPendingChanges.isEmpty();
            boolean additionsPending = !mPendingAdditions.isEmpty();
            if (removalsPending || movesPending || additionsPending || changesPending) {
                Iterator var5 = mPendingRemovals.iterator();
    
                while(var5.hasNext()) {
                    RecyclerView.ViewHolder holder = (RecyclerView.ViewHolder)var5.next();
                    this.animateRemoveImpl(holder);
                }
    
                mPendingRemovals.clear();
                ArrayList additions;
                Runnable adder;
                if (movesPending) {
                    additions = new ArrayList();
                    additions.addAll(this.mPendingMoves);
                    this.mMovesList.add(additions);
                    this.mPendingMoves.clear();
                    final ArrayList finalAdditions2 = additions;
                    adder = new Runnable() {
                        public void run() {
                            Iterator var1 = finalAdditions2.iterator();
    
                            while(var1.hasNext()) {
                                MyCustomItemAnimator.MoveInfo moveInfo = (MyCustomItemAnimator.MoveInfo)var1.next();
                                animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, moveInfo.toX, moveInfo.toY);
                            }
    
                            finalAdditions2.clear();
                            mMovesList.remove(finalAdditions2);
                        }
                    };
                    if (removalsPending) {
                        View view = ((MyCustomItemAnimator.MoveInfo)additions.get(0)).holder.itemView;
                        ViewCompat.postOnAnimationDelayed(view, adder, this.getRemoveDuration());
                    } else {
                        adder.run();
                    }
                }
    
                if (changesPending) {
                    additions = new ArrayList();
                    additions.addAll(this.mPendingChanges);
                    mChangesList.add(additions);
                    this.mPendingChanges.clear();
                    final ArrayList finalAdditions1 = additions;
                    adder = new Runnable() {
                        public void run() {
                            Iterator var1 = finalAdditions1.iterator();
    
                            while(var1.hasNext()) {
                                MyCustomItemAnimator.ChangeInfo change = (MyCustomItemAnimator.ChangeInfo)var1.next();
                                animateChangeImpl(change);
                            }
    
                            finalAdditions1.clear();
                            mChangesList.remove(finalAdditions1);
                        }
                    };
                    if (removalsPending) {
                        RecyclerView.ViewHolder holder = ((MyCustomItemAnimator.ChangeInfo)additions.get(0)).oldHolder;
                        ViewCompat.postOnAnimationDelayed(holder.itemView, adder, this.getRemoveDuration());
                    } else {
                        adder.run();
                    }
                }
    
                if (additionsPending) {
                    additions = new ArrayList();
                    additions.addAll(this.mPendingAdditions);
                    this.mAdditionsList.add(additions);
                    this.mPendingAdditions.clear();
                    final ArrayList finalAdditions = additions;
                    adder = new Runnable() {
                        public void run() {
                            Iterator var1 = finalAdditions.iterator();
    
                            while(var1.hasNext()) {
                                RecyclerView.ViewHolder holder = (RecyclerView.ViewHolder)var1.next();
                                animateAddImpl(holder);
                            }
    
                            finalAdditions.clear();
                            mAdditionsList.remove(finalAdditions);
                        }
                    };
                    if (!removalsPending && !movesPending && !changesPending) {
                        adder.run();
                    } else {
                        long removeDuration = removalsPending ? this.getRemoveDuration() : 0L;
                        long moveDuration = movesPending ? this.getMoveDuration() : 0L;
                        long changeDuration = changesPending ? this.getChangeDuration() : 0L;
                        long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
                        View view = ((RecyclerView.ViewHolder)additions.get(0)).itemView;
                        ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
                    }
                }
    
            }
        }
    
        @Override
        public void endAnimation(RecyclerView.ViewHolder item) {
            super.endAnimation(item);
        }
    
        @Override
        public boolean isRunning() {
            //用于判断动画是否正在执行
            return super.isRunning();
        }
    
        @Override
        public void endAnimations() {
            super.endAnimations();
        }
    
        /**
         * Item状态改变时的动画
         * @param changeInfo
         */
        void animateChangeImpl(final MyCustomItemAnimator.ChangeInfo changeInfo) {
            RecyclerView.ViewHolder holder = changeInfo.oldHolder;
            final View view = holder == null ? null : holder.itemView;
            RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
            final View newView = newHolder != null ? newHolder.itemView : null;
            ViewPropertyAnimator newViewAnimation;
            if (view != null) {
                newViewAnimation = view.animate().setDuration(this.getChangeDuration());
                mChangeAnimations.add(changeInfo.oldHolder);
                newViewAnimation.translationX((float)(changeInfo.toX - changeInfo.fromX));
                newViewAnimation.translationY((float)(changeInfo.toY - changeInfo.fromY));
                final ViewPropertyAnimator finalNewViewAnimation = newViewAnimation;
                newViewAnimation.alpha(0.0F).setListener(new AnimatorListenerAdapter() {
                    public void onAnimationStart(Animator animator) {
                        dispatchChangeStarting(changeInfo.oldHolder, true);
                    }
    
                    public void onAnimationEnd(Animator animator) {
                        finalNewViewAnimation.setListener((Animator.AnimatorListener)null);
                        view.setAlpha(1.0F);
                        view.setTranslationX(0.0F);
                        view.setTranslationY(0.0F);
                        dispatchChangeFinished(changeInfo.oldHolder, true);
                        mChangeAnimations.remove(changeInfo.oldHolder);
                        if (!isRunning()) {
                            dispatchAnimationsFinished();
                        }
                    }
                }).start();
            }
    
            if (newView != null) {
                newViewAnimation = newView.animate();
                this.mChangeAnimations.add(changeInfo.newHolder);
                final ViewPropertyAnimator finalNewViewAnimation1 = newViewAnimation;
                newViewAnimation.translationX(0.0F).translationY(0.0F).setDuration(this.getChangeDuration()).alpha(1.0F).setListener(new AnimatorListenerAdapter() {
                    public void onAnimationStart(Animator animator) {
                        dispatchChangeStarting(changeInfo.newHolder, false);
                    }
    
                    public void onAnimationEnd(Animator animator) {
                        finalNewViewAnimation1.setListener((Animator.AnimatorListener)null);
                        newView.setAlpha(1.0F);
                        newView.setTranslationX(0.0F);
                        newView.setTranslationY(0.0F);
                        dispatchChangeFinished(changeInfo.newHolder, false);
                        mChangeAnimations.remove(changeInfo.newHolder);
                        if (!isRunning()) {
                            dispatchAnimationsFinished();
                        }
                    }
                }).start();
            }
    
        }
    
        /**
         * Item移动实现
         * @param holder
         * @param fromX
         * @param fromY
         * @param toX
         * @param toY
         */
        void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            final View view = holder.itemView;
            final int deltaX = toX - fromX;
            final int deltaY = toY - fromY;
            if (deltaX != 0) {
                view.animate().translationX(0.0F);
            }
    
            if (deltaY != 0) {
                view.animate().translationY(0.0F);
            }
    
            final ViewPropertyAnimator animation = view.animate();
            this.mMoveAnimations.add(holder);
            animation.setDuration(this.getMoveDuration()).setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchMoveStarting(holder);
                }
    
                public void onAnimationCancel(Animator animator) {
                    if (deltaX != 0) {
                        view.setTranslationX(0.0F);
                    }
    
                    if (deltaY != 0) {
                        view.setTranslationY(0.0F);
                    }
    
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    dispatchMoveFinished(holder);
                    mMoveAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    
        /**
         * 添加Item动画实现
         * @param holder
         */
        void animateAddImpl(final RecyclerView.ViewHolder holder) {
            final View view = holder.itemView;
            final ViewPropertyAnimator animation = view.animate();
            this.mAddAnimations.add(holder);
            animation.alpha(1.0F).setDuration(this.getAddDuration()).setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchAddStarting(holder);
                }
    
                public void onAnimationCancel(Animator animator) {
                    view.setAlpha(1.0F);
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    dispatchAddFinished(holder);
                    mAddAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    
        /**
         * 移除Item动画实现
         * @param holder
         */
        private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
            final View view = holder.itemView;
            final ViewPropertyAnimator animation = view.animate();
            this.mRemoveAnimations.add(holder);
            animation.setDuration(this.getRemoveDuration()).alpha(0.0F).setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchRemoveStarting(holder);
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    view.setAlpha(1.0F);
                    dispatchRemoveFinished(holder);
                    mRemoveAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    
        private static class MoveInfo {
            public RecyclerView.ViewHolder holder;
            public int fromX;
            public int fromY;
            public int toX;
            public int toY;
    
            MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
                this.holder = holder;
                this.fromX = fromX;
                this.fromY = fromY;
                this.toX = toX;
                this.toY = toY;
            }
        }
    
        private static class ChangeInfo {
            public RecyclerView.ViewHolder oldHolder;
            public RecyclerView.ViewHolder newHolder;
            public int fromX;
            public int fromY;
            public int toX;
            public int toY;
    
            private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
                this.oldHolder = oldHolder;
                this.newHolder = newHolder;
            }
    
            ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
                this(oldHolder, newHolder);
                this.fromX = fromX;
                this.fromY = fromY;
                this.toX = toX;
                this.toY = toY;
            }
    
            public String toString() {
                return "ChangeInfo{oldHolder=" + this.oldHolder + ", newHolder=" + this.newHolder + ", fromX=" + this.fromX + ", fromY=" + this.fromY + ", toX=" + this.toX + ", toY=" + this.toY + '}';
            }
        }
    }
    

    以上代码算是照搬DefaultItemAnimator源码,接下来回基于已整理好的代码上修改动画。

    【第四步】 修改添加条目动画

        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            //添加条目动画实现
    
            //开始重置动画
            holder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(holder);
    
            //让被添加的条目初始完全透明
            holder.itemView.setAlpha(0.0f);
    
            //把即将被添加的ViewHolder暂时缓存到mPendingAdditions中
            mPendingAdditions.add(holder);
            return true;
        }
    

    这个方法的执行比较频繁,这里保持默认,先重置动画,再将Item完全透明,最后将ViewHolder添加到mPendingAdditions集合中。

        /**
         * 添加Item动画实现
         * @param holder
         */
        void animateAddImpl(final RecyclerView.ViewHolder holder) {
            final View view = holder.itemView;
            final ViewPropertyAnimator animation = view.animate();
            this.mAddAnimations.add(holder);
            animation.alpha(1.0F).setDuration(2000).setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchAddStarting(holder);
                }
    
                public void onAnimationCancel(Animator animator) {
                    view.setAlpha(1.0F);
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    dispatchAddFinished(holder);
                    mAddAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    

    animateAddImpl方法基本也没有变化,只是将动画时长改成2000ms。

    当ViewHolder不可复用时,它的执行效果如下:

    136.gif

    当ViewHolder可复用时,它的执行效果如下:

    138.gif

    【第五步】 修改位移动画

    位移动画本身就写的挺不错了,这里偷个懒就只将动画时间修改为1秒。

    位移动画主要体现在新增条目和删除条目上。

    效果如下:(由于添加动画被完全透明了,所以这里只展示ViewHolder被复用的情况)

    139.gif

    【第六步】 修改删除动画

    修改之后的代码如下:

        /**
         * 移除Item动画实现
         * @param holder
         */
        private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
            final View view = holder.itemView;
            final ViewPropertyAnimator animation = view.animate();
            this.mRemoveAnimations.add(holder);
            animation.setDuration(1000)
                    .translationX(holder.itemView.getWidth())
                    .setInterpolator(new AnticipateOvershootInterpolator())
                    .setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchRemoveStarting(holder);
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    view.setTranslationX(0);
                    dispatchRemoveFinished(holder);
                    mRemoveAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    

    ViewHolder不可被复用的效果如下:

    141.gif

    ViewHolder可被复用的效果如下:

    140.gif

    【第七步】 修改状态改变时的动画

    修改后的代码如下:

        @Override
        public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
            //改变条目动画实现
    
            float prevTranslationX = oldHolder.itemView.getTranslationX();
            float prevTranslationY = oldHolder.itemView.getTranslationY();
            float prevAlpha = oldHolder.itemView.getAlpha();
    
            //开始重置动画
            oldHolder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(oldHolder);
    
            int deltaX = (int)((float)(toX - fromX) - prevTranslationX);
            int deltaY = (int)((float)(toY - fromY) - prevTranslationY);
            oldHolder.itemView.setTranslationX(prevTranslationX);
            oldHolder.itemView.setTranslationY(prevTranslationY);
            oldHolder.itemView.setAlpha(prevAlpha);
            if (newHolder != null) {
    
                //开始重置动画
                newHolder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
                endAnimation(newHolder);
    
                newHolder.itemView.setTranslationX((float)(-deltaX));
                newHolder.itemView.setTranslationY((float)(-deltaY));
                newHolder.itemView.setAlpha(0.0F);
            }
    
            this.mPendingChanges.add(new MyCustomItemAnimator.ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
            return true;
        }
    

    在初始化的时候,oldHolder的透明度保持不变,newHolder给它完全透明。

        /**
         * Item状态改变时的动画
         * @param changeInfo
         */
        void animateChangeImpl(final MyCustomItemAnimator.ChangeInfo changeInfo) {
            RecyclerView.ViewHolder holder = changeInfo.oldHolder;
            final View view = holder == null ? null : holder.itemView;
            RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
            final View newView = newHolder != null ? newHolder.itemView : null;
            ViewPropertyAnimator newViewAnimation;
            if (view != null) {
                newViewAnimation = view.animate().setDuration(2000);
                mChangeAnimations.add(changeInfo.oldHolder);
                newViewAnimation.translationX((float)(changeInfo.toX - changeInfo.fromX));
                newViewAnimation.translationY((float)(changeInfo.toY - changeInfo.fromY));
                final ViewPropertyAnimator finalNewViewAnimation = newViewAnimation;
                newViewAnimation.alpha(0.0F).setListener(new AnimatorListenerAdapter() {
                    public void onAnimationStart(Animator animator) {
                        dispatchChangeStarting(changeInfo.oldHolder, true);
                    }
    
                    public void onAnimationEnd(Animator animator) {
                        finalNewViewAnimation.setListener((Animator.AnimatorListener)null);
                        view.setAlpha(1.0F);
                        view.setTranslationX(0.0F);
                        view.setTranslationY(0.0F);
                        dispatchChangeFinished(changeInfo.oldHolder, true);
                        mChangeAnimations.remove(changeInfo.oldHolder);
                        if (!isRunning()) {
                            dispatchAnimationsFinished();
                        }
                    }
                }).start();
            }
    
            if (newView != null) {
                newViewAnimation = newView.animate();
                this.mChangeAnimations.add(changeInfo.newHolder);
                final ViewPropertyAnimator finalNewViewAnimation1 = newViewAnimation;
                newViewAnimation
                        .setDuration(2000)
                        .alpha(1.0F)
                        .setListener(new AnimatorListenerAdapter() {
                    public void onAnimationStart(Animator animator) {
                        dispatchChangeStarting(changeInfo.newHolder, false);
                    }
    
                    public void onAnimationEnd(Animator animator) {
                        finalNewViewAnimation1.setListener((Animator.AnimatorListener)null);
                        newView.setAlpha(1.0F);
                        newView.setTranslationX(0.0F);
                        newView.setTranslationY(0.0F);
                        dispatchChangeFinished(changeInfo.newHolder, false);
                        mChangeAnimations.remove(changeInfo.newHolder);
                        if (!isRunning()) {
                            dispatchAnimationsFinished();
                        }
                    }
                }).start();
            }
    

    oldHolder透明度从1到0的动画,newHolder透明度从0到1的动画,动画时长为2000ms,效果如下:

    142.gif

    最后,贴出MyCustomItemAnimator类的全部代码

    public class MyCustomItemAnimator extends DefaultItemAnimator {
    
        //用于存储将要移动的MoveInfo对象
        private ArrayList<MyCustomItemAnimator.MoveInfo> mPendingMoves = new ArrayList();
        //MoveInfo的临时存储集合
        private ArrayList<ArrayList<MyCustomItemAnimator.MoveInfo>> mMovesList = new ArrayList();
        //用于存储正在执行移动动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList();
        //用于存储将要被添加的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList();
        //存储被添加的ViewHolder的临时集合
        private ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList();
        //用于存储正在执行添加动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList();
        //用于存储将要删除的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList();
        //用于存储正在执行删除动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList();
        //用于存储将要改变的ViewHolder
        private ArrayList<MyCustomItemAnimator.ChangeInfo> mPendingChanges = new ArrayList();
        //存储被改变的ViewHolder的临时集合
        private ArrayList<ArrayList<MyCustomItemAnimator.ChangeInfo>> mChangesList = new ArrayList();
        //用于存储正在执行改变动画的ViewHolder
        private ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList();
    
        //定义一个插值器:先向相反方向改变,再加速播放,会超出目标值
        private AnticipateOvershootInterpolator accelerateDecelerateInterpolator;
    
        @Override
        public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
            return true;
        }
    
    
        @Override
        public boolean animateAdd(RecyclerView.ViewHolder holder) {
            //添加条目动画实现
    
            //开始重置动画
            holder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(holder);
    
            //让被添加的条目初始完全透明
            holder.itemView.setAlpha(0.0f);
    
            //把即将被添加的ViewHolder暂时缓存到mPendingAdditions中
            mPendingAdditions.add(holder);
            return true;
        }
    
    
        @Override
        public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            //移动条目动画实现
    
            View view = holder.itemView;
            fromX += (int)holder.itemView.getTranslationX();
            fromY += (int)holder.itemView.getTranslationY();
    
            //开始重置动画
            holder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(holder);
    
            int deltaX = toX - fromX;
            int deltaY = toY - fromY;
            if (deltaX == 0 && deltaY == 0) {
                dispatchMoveFinished(holder);
                return false;
            } else {
                if (deltaX != 0) {
                    view.setTranslationX((float)(-deltaX));
                }
    
                if (deltaY != 0) {
                    view.setTranslationY((float)(-deltaY));
                }
    
                mPendingMoves.add(new MyCustomItemAnimator.MoveInfo(holder, fromX, fromY, toX, toY));
                return true;
            }
        }
    
        @Override
        public boolean animateRemove(RecyclerView.ViewHolder holder) {
            //删除条目动画实现
    
            //开始重置动画
            holder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(holder);
    
            //把将要执行删除动画的ViewHolder放入mPendingRemovals集合
            mPendingRemovals.add(holder);
            return true;
        }
    
        @Override
        public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
            //改变条目动画实现
    
            float prevTranslationX = oldHolder.itemView.getTranslationX();
            float prevTranslationY = oldHolder.itemView.getTranslationY();
            float prevAlpha = oldHolder.itemView.getAlpha();
    
            //开始重置动画
            oldHolder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
            endAnimation(oldHolder);
    
            int deltaX = (int)((float)(toX - fromX) - prevTranslationX);
            int deltaY = (int)((float)(toY - fromY) - prevTranslationY);
            oldHolder.itemView.setTranslationX(prevTranslationX);
            oldHolder.itemView.setTranslationY(prevTranslationY);
            oldHolder.itemView.setAlpha(prevAlpha);
            if (newHolder != null) {
    
                //开始重置动画
                newHolder.itemView.animate().setInterpolator((new ValueAnimator()).getInterpolator());
                endAnimation(newHolder);
    
                newHolder.itemView.setTranslationX((float)(-deltaX));
                newHolder.itemView.setTranslationY((float)(-deltaY));
                newHolder.itemView.setAlpha(0.0F);
            }
    
            this.mPendingChanges.add(new MyCustomItemAnimator.ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
            return true;
        }
    
        @Override
        public void runPendingAnimations() {
            boolean removalsPending = !mPendingRemovals.isEmpty();
            boolean movesPending = !mPendingMoves.isEmpty();
            boolean changesPending = !mPendingChanges.isEmpty();
            boolean additionsPending = !mPendingAdditions.isEmpty();
            if (removalsPending || movesPending || additionsPending || changesPending) {
                Iterator var5 = mPendingRemovals.iterator();
    
                while(var5.hasNext()) {
                    RecyclerView.ViewHolder holder = (RecyclerView.ViewHolder)var5.next();
                    this.animateRemoveImpl(holder);
                }
    
                mPendingRemovals.clear();
                ArrayList additions;
                Runnable adder;
                if (movesPending) {
                    additions = new ArrayList();
                    additions.addAll(this.mPendingMoves);
                    this.mMovesList.add(additions);
                    this.mPendingMoves.clear();
                    final ArrayList finalAdditions2 = additions;
                    adder = new Runnable() {
                        public void run() {
                            Iterator var1 = finalAdditions2.iterator();
    
                            while(var1.hasNext()) {
                                MyCustomItemAnimator.MoveInfo moveInfo = (MyCustomItemAnimator.MoveInfo)var1.next();
                                animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, moveInfo.toX, moveInfo.toY);
                            }
    
                            finalAdditions2.clear();
                            mMovesList.remove(finalAdditions2);
                        }
                    };
                    if (removalsPending) {
                        View view = ((MyCustomItemAnimator.MoveInfo)additions.get(0)).holder.itemView;
                        ViewCompat.postOnAnimationDelayed(view, adder, this.getRemoveDuration());
                    } else {
                        adder.run();
                    }
                }
    
                if (changesPending) {
                    additions = new ArrayList();
                    additions.addAll(this.mPendingChanges);
                    mChangesList.add(additions);
                    this.mPendingChanges.clear();
                    final ArrayList finalAdditions1 = additions;
                    adder = new Runnable() {
                        public void run() {
                            Iterator var1 = finalAdditions1.iterator();
    
                            while(var1.hasNext()) {
                                MyCustomItemAnimator.ChangeInfo change = (MyCustomItemAnimator.ChangeInfo)var1.next();
                                animateChangeImpl(change);
                            }
    
                            finalAdditions1.clear();
                            mChangesList.remove(finalAdditions1);
                        }
                    };
                    if (removalsPending) {
                        RecyclerView.ViewHolder holder = ((MyCustomItemAnimator.ChangeInfo)additions.get(0)).oldHolder;
                        ViewCompat.postOnAnimationDelayed(holder.itemView, adder, this.getRemoveDuration());
                    } else {
                        adder.run();
                    }
                }
    
                if (additionsPending) {
                    additions = new ArrayList();
                    additions.addAll(this.mPendingAdditions);
                    this.mAdditionsList.add(additions);
                    this.mPendingAdditions.clear();
                    final ArrayList finalAdditions = additions;
                    adder = new Runnable() {
                        public void run() {
                            Iterator var1 = finalAdditions.iterator();
    
                            while(var1.hasNext()) {
                                RecyclerView.ViewHolder holder = (RecyclerView.ViewHolder)var1.next();
                                animateAddImpl(holder);
                            }
    
                            finalAdditions.clear();
                            mAdditionsList.remove(finalAdditions);
                        }
                    };
                    if (!removalsPending && !movesPending && !changesPending) {
                        adder.run();
                    } else {
                        long removeDuration = removalsPending ? this.getRemoveDuration() : 0L;
                        long moveDuration = movesPending ? this.getMoveDuration() : 0L;
                        long changeDuration = changesPending ? this.getChangeDuration() : 0L;
                        long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
                        View view = ((RecyclerView.ViewHolder)additions.get(0)).itemView;
                        ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
                    }
                }
    
            }
        }
    
        @Override
        public void endAnimation(RecyclerView.ViewHolder item) {
            super.endAnimation(item);
        }
    
        @Override
        public boolean isRunning() {
            //用于判断动画是否正在执行
            return super.isRunning();
        }
    
        @Override
        public void endAnimations() {
            super.endAnimations();
        }
    
        /**
         * Item状态改变时的动画
         * @param changeInfo
         */
        void animateChangeImpl(final MyCustomItemAnimator.ChangeInfo changeInfo) {
            RecyclerView.ViewHolder holder = changeInfo.oldHolder;
            final View view = holder == null ? null : holder.itemView;
            RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
            final View newView = newHolder != null ? newHolder.itemView : null;
            ViewPropertyAnimator newViewAnimation;
            if (view != null) {
                newViewAnimation = view.animate().setDuration(2000);
                mChangeAnimations.add(changeInfo.oldHolder);
                newViewAnimation.translationX((float)(changeInfo.toX - changeInfo.fromX));
                newViewAnimation.translationY((float)(changeInfo.toY - changeInfo.fromY));
                final ViewPropertyAnimator finalNewViewAnimation = newViewAnimation;
                newViewAnimation.alpha(0.0F).setListener(new AnimatorListenerAdapter() {
                    public void onAnimationStart(Animator animator) {
                        dispatchChangeStarting(changeInfo.oldHolder, true);
                    }
    
                    public void onAnimationEnd(Animator animator) {
                        finalNewViewAnimation.setListener((Animator.AnimatorListener)null);
                        view.setAlpha(1.0F);
                        view.setTranslationX(0.0F);
                        view.setTranslationY(0.0F);
                        dispatchChangeFinished(changeInfo.oldHolder, true);
                        mChangeAnimations.remove(changeInfo.oldHolder);
                        if (!isRunning()) {
                            dispatchAnimationsFinished();
                        }
                    }
                }).start();
            }
    
            if (newView != null) {
                newViewAnimation = newView.animate();
                this.mChangeAnimations.add(changeInfo.newHolder);
                final ViewPropertyAnimator finalNewViewAnimation1 = newViewAnimation;
                newViewAnimation
                        .setDuration(2000)
                        .alpha(1.0F)
                        .setListener(new AnimatorListenerAdapter() {
                    public void onAnimationStart(Animator animator) {
                        dispatchChangeStarting(changeInfo.newHolder, false);
                    }
    
                    public void onAnimationEnd(Animator animator) {
                        finalNewViewAnimation1.setListener((Animator.AnimatorListener)null);
                        newView.setAlpha(1.0F);
                        newView.setTranslationX(0.0F);
                        newView.setTranslationY(0.0F);
                        dispatchChangeFinished(changeInfo.newHolder, false);
                        mChangeAnimations.remove(changeInfo.newHolder);
                        if (!isRunning()) {
                            dispatchAnimationsFinished();
                        }
                    }
                }).start();
            }
    
        }
    
        /**
         * Item移动实现
         * @param holder
         * @param fromX
         * @param fromY
         * @param toX
         * @param toY
         */
        void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
            final View view = holder.itemView;
            final int deltaX = toX - fromX;
            final int deltaY = toY - fromY;
            if (deltaX != 0) {
                view.animate().translationX(0.0F);
            }
    
            if (deltaY != 0) {
                view.animate().translationY(0.0F);
            }
    
            final ViewPropertyAnimator animation = view.animate();
            this.mMoveAnimations.add(holder);
            animation.setDuration(1000).setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchMoveStarting(holder);
                }
    
                public void onAnimationCancel(Animator animator) {
                    if (deltaX != 0) {
                        view.setTranslationX(0.0F);
                    }
    
                    if (deltaY != 0) {
                        view.setTranslationY(0.0F);
                    }
    
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    dispatchMoveFinished(holder);
                    mMoveAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    
        /**
         * 添加Item动画实现
         * @param holder
         */
        void animateAddImpl(final RecyclerView.ViewHolder holder) {
            final View view = holder.itemView;
            final ViewPropertyAnimator animation = view.animate();
            this.mAddAnimations.add(holder);
            animation.alpha(1.0F).setDuration(2000).setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchAddStarting(holder);
                }
    
                public void onAnimationCancel(Animator animator) {
                    view.setAlpha(1.0F);
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    dispatchAddFinished(holder);
                    mAddAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    
        /**
         * 移除Item动画实现
         * @param holder
         */
        private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
            final View view = holder.itemView;
            final ViewPropertyAnimator animation = view.animate();
            this.mRemoveAnimations.add(holder);
            animation.setDuration(1000)
                    .translationX(holder.itemView.getWidth())
                    .setInterpolator(new AnticipateOvershootInterpolator())
                    .setListener(new AnimatorListenerAdapter() {
                public void onAnimationStart(Animator animator) {
                    dispatchRemoveStarting(holder);
                }
    
                public void onAnimationEnd(Animator animator) {
                    animation.setListener((Animator.AnimatorListener)null);
                    view.setTranslationX(0);
                    dispatchRemoveFinished(holder);
                    mRemoveAnimations.remove(holder);
                    if (!isRunning()) {
                        dispatchAnimationsFinished();
                    }
                }
            }).start();
        }
    
        private static class MoveInfo {
            public RecyclerView.ViewHolder holder;
            public int fromX;
            public int fromY;
            public int toX;
            public int toY;
    
            MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
                this.holder = holder;
                this.fromX = fromX;
                this.fromY = fromY;
                this.toX = toX;
                this.toY = toY;
            }
        }
    
        private static class ChangeInfo {
            public RecyclerView.ViewHolder oldHolder;
            public RecyclerView.ViewHolder newHolder;
            public int fromX;
            public int fromY;
            public int toX;
            public int toY;
    
            private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
                this.oldHolder = oldHolder;
                this.newHolder = newHolder;
            }
    
            ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
                this(oldHolder, newHolder);
                this.fromX = fromX;
                this.fromY = fromY;
                this.toX = toX;
                this.toY = toY;
            }
    
            public String toString() {
                return "ChangeInfo{oldHolder=" + this.oldHolder + ", newHolder=" + this.newHolder + ", fromX=" + this.fromX + ", fromY=" + this.fromY + ", toX=" + this.toX + ", toY=" + this.toY + '}';
            }
        }
    }
    

    [本章完...]

    相关文章

      网友评论

        本文标题:RecyclerView<第十六篇>:条目动画之自定义Defau

        本文链接:https://www.haomeiwen.com/subject/lzxvjctx.html