相信大家都对RecyclerView
的用法相当熟悉了,RecyclerView
的出现给我们开发者提供了一个高扩展的控件,不管是列表、网格、瀑布流,一个控件就可以搞定,而且神奇的是只需要修改一行代码,就可以轻松切换
。RecyclerView
的好处太多太多,就不一一列举了,网上也有很多关于RecyclerView
的教程。说到这里,我们就开始进入主题了,虽然网上有那么多的RecyclerView
教程,但是没有一篇是详细介绍RecyclerView
的动画的,大部分都是使用默认的DefaultItemAnimator
或者使用第三方的动画库,这篇博客我们就来弥补这个空白,咱们来根据DefaultItemAnimator
的代码来实现一个简单的RecyclerView
动画。
我们仅仅去实现一下最常用的
add
和remove
的动画,其他的动画,如果大家感兴趣,可以自己参考DefaultItemAnimator
去扩展。
在开始之前,我们先来看看实现的效果吧:
如何定制动画呢?首先要继承自RecyclerView.ItemAnimator
这个类,既然要继承这个类,那我们有必要去了解一下这个类和这个类中的几个方法(仅关注我们今天需要的,其他的类同)。
This class defines the animations that take place on items as changes are made to the adapter. Subclasses of ItemAnimator can be used to implement custom animations for actions on ViewHolder items. The RecyclerView will manage retaining these items while they are being animated, but implementors must call the appropriate “Starting” (dispatchRemoveStarting(ViewHolder), dispatchMoveStarting(ViewHolder), dispatchChangeStarting(ViewHolder, boolean), or dispatchAddStarting(ViewHolder)) and “Finished” (dispatchRemoveFinished(ViewHolder), dispatchMoveFinished(ViewHolder), dispatchChangeFinished(ViewHolder, boolean), or dispatchAddFinished(ViewHolder)) methods when each item animation is being started and ended.
只看重点,当开始动画时,我们需要调用dispatchXXXStarting()
,当动画结束时,我们需要调用dispatchXXXFinished()
。
接下来,来看看需要我们去动手实现的几个方法:
isRunning()
返回当前是否有动画需要执行。
runPendingAnimations()
当有动画要执行的时候调用。这里需要说明一点,当我们去add一个item时,动画可能不是立即去执行的,这种机制可以让ItemAnimator一个个的添加,然后一块去执行。
animateAdd()
add时的动画,当我们调用
Adapter.notifyItemInsert()
时会触发该方法,该方法有一个boolean类型的返回值,返回值表示:runPendingAnimations
是否可以在下一个时机去执行。所以当我们定制动画时,这个方法要返回true。与
animateAdd
类似的还有animateMove
、animateRemove
、animateChange
。dispatchAddStarting()
动画开始时调用。
dispatchAddFinished()
动画结束时调用。
dispatchAnimationsFinished()
所有动画结束时调用。
好了,介绍完了几个用到的方法,下面就来动手实现我们自己的动画吧。还是上面说的,我们只实现add
和remove
的动画。模仿着DefaultItemAnimator
算了算,我们需要4个ArrayList
.
private ArrayList<RecyclerView.ViewHolder> mPendingAddHolders =
new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mPendingRemoveHolders =
new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mAddAnimtions = new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
明明就两个动画,怎么需要4个ArrayList
呢?而且还是一对一对的!羡慕不?这里要好好说道说道了。上面说了,动画可能不是立即执行的,而是在runPendingAnimations
中一块去执行