欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

安卓动画(四)Recyclerview ItemAnimator(下)

程序员文章站 2022-05-05 14:33:35
...

安卓动画(三)Recyclerview ItemAnimator(上)
这一篇就实现下面两种效果:
安卓动画(四)Recyclerview ItemAnimator(下)
安卓动画(四)Recyclerview ItemAnimator(下)

demo地址:https://github.com/whoami-I/Animation
实现之前,就是要对系统为我们实现的DefaultItemAnimator这个类进行改造,自己仿照写一个BaseItemAnimator,再在这个类的基础上,自定义我们自己的各种各样的动画,以add动画改造进行举例,DefaultItemAnimator中关于add动画有两个方法:animateAddanimateAddImpl

@Override
    public boolean animateAdd(final RecyclerView.ViewHolder holder) {
        resetAnimation(holder);
        holder.itemView.setAlpha(0);
        mPendingAdditions.add(holder);
        return true;
    }

animateAdd方法很简单,其实是add动画之前的一个初始化流程,为了使这个方法更好的扩展,改造成下面的模式:

@Override
    public boolean animateAdd(final ViewHolder holder) {
        resetAnimation(holder);
        addAnimateInit(holder);
        mPendingAdditions.add(holder);
        return true;
    }
 

addAnimateInit是一个抽象方法,有待于继承,接下来改造animateAddImpl方法,DefaultItemAnimator中是这样的

animation.alpha(1).setDuration(getAddDuration())
                .setListener(new AnimatorListenerAdapter() {
                /*省略*/
                    @Override
                    public void onAnimationEnd(Animator animator) {
                        animation.setListener(null);
                        dispatchAddFinished(holder);
                        mAddAnimations.remove(holder);
                        dispatchFinishedWhenDone();
                    }
                }).start();

改造成:

//添加抽象方法
addAnimationStart(holder,animation);
        animation.setDuration(getAddDuration()).
                setListener(new VpaListenerAdapter() {
                   /*省略*/
                    @Override
                    public void onAnimationEnd(View view) {
                        animation.setListener(null);
                        dispatchAddFinished(holder);
                        /*添加抽象方法*/
                        addAnimationEnd(holder);
                        mAddAnimations.remove(holder);
                        dispatchFinishedWhenDone();
                    }
                }).start();

改造中添加了两个抽象方法,一个是addAnimationStart在这个方法中要做的是动画最终要变成什么样子;当动画结束,又添加了一个抽象方法,对结束可能需要做一些处理。
上面仅仅是对add动画进行了一个改造,相应的remove也可以最终改造出来,因此最终的BaseItemAnimator里面添加了13个抽象的方法,用于处理各种情况,这样我们以ScaleAnimator举例子来实现其中的一些方法:

@Override
    public void removeAnimateInit(RecyclerView.ViewHolder holder) {
    //remove初始化,这时itemView的大小应该是正常大小
        holder.itemView.setScaleX(1);
        holder.itemView.setScaleY(1);
    }

    @Override
    public void removeAnimationStart(RecyclerView.ViewHolder holder, ViewPropertyAnimatorCompat animator) {
    //因为要有一个缩小的动画,因此将动画的最终状态设置为scale为0的大小
        holder.itemView.setPivotX(holder.itemView.getWidth()/2);
        holder.itemView.setPivotY(holder.itemView.getHeight()/2);
        animator.scaleX(0).scaleY(0);
    }
	//当动画结束时,因为此时ViewHolder可能被复用,因此需要将状态设置回来
    @Override
    public void removeAnimationEnd(RecyclerView.ViewHolder holder) {
        holder.itemView.setScaleX(1);
        holder.itemView.setScaleY(1);
    }
	//add动画初始化此时还没添加进来,因此大小为0
    @Override
    public void addAnimateInit(RecyclerView.ViewHolder holder) {
        holder.itemView.setScaleX(0);
        holder.itemView.setScaleY(0);
    }

	//add的最终状态肯定是正常大小
    @Override
    public void addAnimationStart(RecyclerView.ViewHolder holder, ViewPropertyAnimatorCompat animator) {
        ViewCompat.setPivotX(holder.itemView,holder.itemView.getWidth()/2);
        ViewCompat.setPivotY(holder.itemView,holder.itemView.getHeight()/2);
        animator.scaleX(1).scaleY(1);
    }
	//最终大小也肯定是1
    @Override
    public void addAnimationEnd(RecyclerView.ViewHolder holder) {
        ViewCompat.setScaleX(holder.itemView,1);
        ViewCompat.setScaleY(holder.itemView,1);
    }
	//因为可能存在一次add还没完,下一次add又开始的情况,因此这时直接就把上一次结果设置成1
    @Override
    public void addAnimationCancel(RecyclerView.ViewHolder holder) {
        ViewCompat.setScaleX(holder.itemView,1);
        ViewCompat.setScaleY(holder.itemView,1);
    }

好了,这就是scaleAnimator的具体细节,基于这个细节,还能封装Fade、Slide或者各种动画的结合体,具体就看代码吧。
注意:
要实现上面的动画效果,必须是调用notifyItemRemoved等局部刷新数据相关的API,而不能使用notifyDataSetChanged这种全局性更新数据的API

相关标签: 安卓UI