Android动画了解—RecyclerView Animator

Recyclerview animation

什么时候开始的 RecyclerView animation,在我们UI 2.0~3.0的时候,很多地方都需要这种 RecyclerView 界面 初始化添加移除更新 数据的 动画效果样式.

看几个RecycelrView Adapter 初始化的小DEMO
在这里插入图片描述
在这里插入图片描述
除了这种方式进行初始化,我们还可以用前面所讲的过渡动画来进行

Transition explode = new Explode();
explode.setDuration(1000);
TransitionManager.beginDelayedTransition(recyclerView, explode);
if (recyclerView.getAdapter() != null) {
	recyclerView.setAdapter(null);
} else {
	recyclerView.setAdapter(mColorsAdapter);
}

在这里插入图片描述

再看看 RecyclerView Item 添加,移除,更新的的小栗子
在这里插入图片描述

如果没有设置 Item animation,RecyclerView 默认使用的就是 DefaultItemAnimator(继承的 SimpleItemAnimator)

如果想实现上面的一些效果(Demo地址),我们就需要 自定义自己的 Item Animator ,只需要继承 SimpleItemAnimator,重写几个关键的重要函数

函数名 含义
animateRemove item 移除时的动画
animateAdd item 添加时的动画
animateMove 移动时的动画 列表项位置移动时调用
animateChange item 更新时的动画
runPendingAnimations 真正控制执行动画的地方
endAnimation 停止某个Item的动画
endAnimations 停止所有动画
isRunning 返回当前是否有动画需要执行

在自定义Item Animator 中会调用到的相关函数:

函数名 含义
dispatch(Add/Remove/Move/Change)Starting 动画开始时调用,比如Add dispatchAddStarting
dispatch(Add/Remove/Move/Change)Finished 动画结束时调用,比如Add dispatchAddFinished
dispatchAnimationsFinished 所有动画结束时调用

引发 Item 动画的几个函数

Adapter.notifyItemInserted(int position) // 触发 Add Item Animator
Adapter.notifyItemRemoved(int position) // 触发 Remove Item Animator
Adapter.notifyItemChanged(int position) // 触发 Change Item Animator
Adapter.notifyItemMoved(int fromPosition, int  toPosition) // 触发 MoveItem Animator

先来自定义的一个添加Item View的动画效果的小DEMO

public class CumtomAnimator extends SimpleItemAnimator {
	// 保存 需要做 add 动画效果的 itemView 的数组
	private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
	@Override
    public boolean animateAdd(RecyclerView.ViewHolder holder) {
    	// 添加对应的数据,主要用于 runPendingAnimations 执行动画效果
    	mPendingAdditions.add(holder);
    }
    @Override
    public void runPendingAnimations() {
    	for (RecyclerView.ViewHolder holder : mPendingAdditions) {
            ViewCompat.animate(holder.itemView)
                    .scaleX(1.0f)
                    .scaleY(1.0f)
                    .setDuration(getAddDuration())
                    .start();
        }
        // 记得要清理掉,不然其它动画执行后,要被影响,而且也影响 isRunning 的判断
        mPendingAdditions.clear();
	}
	@Override
    public boolean isRunning() {
        return !mPendingAdditions.isEmpty()
               || ... ...
    }
    ... ...
}

ViewCompat:android官方实现兼容的一个帮助类,具体可以查找网上相关资料 官方资料

可以试试(notifyItemInserted(position))有没有动画效果,肯定是没有效果的,因为没有去初始化它 起始的样子!!!
在这里插入图片描述

来改改代码… …

... ...
public boolean animateAdd(RecyclerView.ViewHolder holder) {
	// 初始化动画状态
    // 将 ItemView 设置为 ScaleX,ScaleY 都为0
    // 那么执行动画效果的时候,就是从 中间位置 然后 放大 0.0f -> 1.0f
    View itemView = holder.itemView;
    ViewCompat.setPivotY(itemView, itemView.getMeasuredHeight() / 2);
    ViewCompat.setPivotX(itemView, itemView.getMeasuredWidth() / 2);
    ViewCompat.setScaleX(itemView, 0);
    ViewCompat.setScaleY(itemView, 0);
    // 添加对应的数据,主要用于 runPendingAnimations
    mPendingAdditions.add(holder);
}
... ...

代码修改后,添加 ItemView 就能达到下面的效果。
在这里插入图片描述
你会发现,上面的 RecyclerView ItemView的添加动画效果,还行,就是新增的时候,下面的其它的ItemView 移动的很生硬,所以这里就引出了 animateMove 函数。

函数名 参数 参数含义
animateMove (final ViewHolder holder, int fromX, int fromY, int toX, int toY) 列表项位置移动时调用,移动的ViewHolder;fromX 起始x,y值;toX 目标x,y值
@Override
public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
	// 设置它的初始位置.
	final View view = holder.itemView;
	// 目标的位置 减去 起始位置(原来的位置),得到需要位移的距离
    int deltaX = toX - fromX;
    int deltaY = toY - fromY;
    // 设置后,相当于从 新的位置 回到了 原来的位置上.
    if (deltaX != 0) {
       ViewCompat.setTranslationX(view, -deltaX);
    }
    if (deltaY != 0) {
    	ViewCompat.setTranslationY(view, -deltaY);
    }
    mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
}

@Override
public void runPendingAnimations() {
    ... ...
    // 最后从原来的位置 做动画,回到新的位置上,就完整了移动的动画效果.
	for (MoveInfo moveInfo : mPendingMoves) {
		ViewCompat.animate(moveInfo.holder.itemView)
                  .translationX(0)
                  .translationY(0)
                  .setDuration(getMoveDuration())
                  .start();
	}
	mPendingMoves.clear();
	... ...
}

整个添加Item View的动画效果,就这样完成啦!!!
在这里插入图片描述
当然在项目,肯定没有那么简单,这里只是简单的举个小栗子,给大家说明下几个函数的重要性.

如果是项目中使用,只需要继承这个 BaseitemAnimator,写一些自己想要的效果就OK,不过这里已经实现了大多数的动画效果。
在这里插入图片描述 在这里插入图片描述
需要使用以上效果的小伙伴,自行下载,代码库地址
在这里插入图片描述

5.x 参考资料

RecyclerView animations 国外大神文章
RecyclerView anim视频

掌握RecyclerView动画不得不看的文章

谷歌API文档

深入理解 RecyclerView 系列之二:ItemAnimator

自定义RecyclerView ItemAnimator 上

自定义RecyclerView ItemAnimator 下


Android动画了解—转场/过渡(Transition) 动画<=上个章节 下个章节=> Android动画了解—其它动画

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章