转载请标明出处:/zhaoyanjun6/article/details/111650621
本文出自【赵彦军的博客】
文章目录
ViewPropertyAnimator源码分析animate()withStartAction() 是如何在动画执行之前执行的取消动画实战例子ViewPropertyAnimator
ViewPropertyAnimator
是在3.1系统中加入的,ViewPropertyAnimator
跟ObjectAnimator
很像,也能改变View
的实际值,但是ViewPropertyAnimator
只能作用于View
而不能作用于其他object
。假如需要同时对多个属性执行动画时,ViewPropertyAnimator
效率更高,代码更简洁、更易读。
源码分析
animate()
/*** This method returns a ViewPropertyAnimator object, which can be used to animate* specific properties on this View.** @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.*/public ViewPropertyAnimator animate() {if (mAnimator == null) {mAnimator = new ViewPropertyAnimator(this);}return mAnimator;}
withStartAction() 是如何在动画执行之前执行的
/*** Specifies an action to take place when the next animation runs. If there is a* {@link #setStartDelay(long) startDelay} set on this ViewPropertyAnimator, then the* action will run after that startDelay expires, when the actual animation begins.* This method, along with {@link #withEndAction(Runnable)}, is intended to help facilitate* choreographing ViewPropertyAnimator animations with other animations or actions* in the application.** @param runnable The action to run when the next animation starts.* @return This object, allowing calls to methods in this class to be chained.*/public ViewPropertyAnimator withStartAction(Runnable runnable) {mPendingOnStartAction = runnable;if (runnable != null && mAnimatorOnStartMap == null) {mAnimatorOnStartMap = new HashMap<Animator, Runnable>();}return this;}
withStartAction
方法,会把runnable
实例放在map
中,然后放在onAnimationStart
方法中执行。
取消动画
/*** Cancels all property animations that are currently running or pending.*/public void cancel() {if (mAnimatorMap.size() > 0) {HashMap<Animator, PropertyBundle> mAnimatorMapCopy =(HashMap<Animator, PropertyBundle>)mAnimatorMap.clone();Set<Animator> animatorSet = mAnimatorMapCopy.keySet();for (Animator runningAnim : animatorSet) {runningAnim.cancel();}}mPendingAnimations.clear();mPendingSetupAction = null;mPendingCleanupAction = null;mPendingOnStartAction = null;mPendingOnEndAction = null;mView.removeCallbacks(mAnimationStarter);}
实战例子
写一个小例子:
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)var button: Button = findViewById(R.id.bt)button.animate().translationX(150f) //x轴向右平移.translationY(100f) //y轴向下平移.scaleX(1.5f) //x方向放大1.5倍.scaleY(2f) //y方向放大2倍.setStartDelay(2000) //延时2000秒,才开始执行动画.setInterpolator(DecelerateInterpolator()) //设置减速插值器.setDuration(800) //动画执行时长800毫秒.setListener(object : Animator.AnimatorListener {override fun onAnimationStart(animation: Animator?) {}override fun onAnimationEnd(animation: Animator?) {}override fun onAnimationCancel(animation: Animator?) {}override fun onAnimationRepeat(animation: Animator?) {}}).start() //开始执行}}
效果图:
有几个细节还是值得大家注意一下:
整个ViewPropertyAnimator的功能都是建立在View类新增的animate()方法之上的,这个方法会创建并返回一个ViewPropertyAnimator的实例,之后的调用的所有方法,设置的所有属性都是通过这个实例完成的。大家注意到,在使用ViewPropertyAnimator时,我们自始至终没有调用过start()方法,这是因为新的接口中使用了隐式启动动画的功能,只要我们将动画定义完成之后,动画就会自动启动。并且这个机制对于组合动画也同样有效,只要我们不断地连缀新的方法,那么动画就不会立刻执行,等到所有在ViewPropertyAnimator上设置的方法都执行完毕后,动画就会自动启动。当然如果不想使用这一默认机制的话,我们也可以显式地调用start()方法来启动动画。ViewPropertyAnimator的所有接口都是使用连缀的语法来设计的,每个方法的返回值都是它自身的实例,因此调用完一个方法之后可以直接连缀调用它的另一个方法,这样把所有的功能都串接起来,我们甚至可以仅通过一行代码就完成任意复杂度的动画功能。