以下内容是根据《第一行代码》作者的微信公众号里面的文章写的,算是做了个笔记!
内容
1.补间动画缺点
2.属性动画定义
3.ValueAnimator
4.ObjectAnimator
5.AnimatorSet
6.Animator监听器
一.补间动画缺点
①无法对一个非View的对象进行动画操作
②补间动画只能够实现移动、缩放、旋转和淡入淡出这四种动画操作
③补间动画只是改变了View的显示效果而已,而不会真正去改变View的属性
二.属性动画定义
属性动画已经不再是针对于View来设计的了,也不限定于只能实现移动、缩放、旋转和淡入淡出这几种动画操作,同时也不再只是一种视觉上的动画效果了。
它实际上是一种不断地对值进行操作的机制,并将值赋值到指定对象的指定属性上,可以是任意对象的任意属性
所以我们仍然可以将一个View进行移动或者缩放,但同时也可以对自定义View中的Point对象进行动画操作了。我们只需要告诉系统动画的运行时长,需要执行哪种类型的动画,以及动画的初始值和结束值,剩下的工作就可以全部交给系统去完成了。
三.ValueAnimator
ValueAnimator是整个属性动画机制当中最核心的一个类,前面我们已经提到了,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。
button.setOnClickListener {var anim = ValueAnimator.ofFloat(0f,1f)
anim.duration = 1000
anim.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener{
override fun onAnimationUpdate(animation: ValueAnimator?) {
var currentValue = animation?.getAnimatedValue()
Log.v("ljh","currentValue = $currentValue")
}
})
//千万不要忘记start
anim.start()
}
就会打印出如下结果
2020-08-22 15:39:57.217 5471-5471/com.example.new_animation V/ljh: currentValue = 0.02020-08-22 15:39:57.233 5471-5471/com.example.new_animation V/ljh: currentValue = 0.0
2020-08-22 15:39:57.250 5471-5471/com.example.new_animation V/ljh: currentValue = 0.0026845932
2020-08-22 15:39:57.268 5471-5471/com.example.new_animation V/ljh: currentValue = 0.0061558187
2020-08-22 15:39:57.287 5471-5471/com.example.new_animation V/ljh: currentValue = 0.011035353
2020-08-22 15:39:57.302 5471-5471/com.example.new_animation V/ljh: currentValue = 0.01690182
2020-08-22 15:39:57.318 5471-5471/com.example.new_animation V/ljh: currentValue = 0.02447176
2020-08-22 15:39:57.334 5471-5471/com.example.new_animation V/ljh: currentValue = 0.033397675
2020-08-22 15:39:57.352 5471-5471/com.example.new_animation V/ljh: currentValue = 0.043014556
2020-08-22 15:39:57.367 5471-5471/com.example.new_animation V/ljh: currentValue = 0.054496735
2020-08-22 15:39:57.386 5471-5471/com.example.new_animation V/ljh: currentValue = 0.06724939
2020-08-22 15:39:57.405 5471-5471/com.example.new_animation V/ljh: currentValue = 0.080379754
2020-08-22 15:39:57.418 5471-5471/com.example.new_animation V/ljh: currentValue = 0.09549156
2020-08-22 15:39:57.434 5471-5471/com.example.new_animation V/ljh: currentValue = 0.11175674
2020-08-22 15:39:57.451 5471-5471/com.example.new_animation V/ljh: currentValue = 0.12807748
2020-08-22 15:39:57.469 5471-5471/com.example.new_animation V/ljh: currentValue = 0.14644662
2020-08-22 15:39:57.485 5471-5471/com.example.new_animation V/ljh: currentValue = 0.16582394
2020-08-22 15:39:57.501 5471-5471/com.example.new_animation V/ljh: currentValue = 0.18493307
2020-08-22 15:39:57.517 5471-5471/com.example.new_animation V/ljh: currentValue = 0.20610732
2020-08-22 15:39:57.534 5471-5471/com.example.new_animation V/ljh: currentValue = 0.22811979
2020-08-22 15:39:57.551 5471-5471/com.example.new_animation V/ljh: currentValue = 0.24954662
2020-08-22 15:39:57.568 5471-5471/com.example.new_animation V/ljh: currentValue = 0.27300477
2020-08-22 15:39:57.585 5471-5471/com.example.new_animation V/ljh: currentValue = 0.29711008
2020-08-22 15:39:57.602 5471-5471/com.example.new_animation V/ljh: currentValue = 0.32032734
2020-08-22 15:39:57.619 5471-5471/com.example.new_animation V/ljh: currentValue = 0.34549147
2020-08-22 15:39:57.635 5471-5471/com.example.new_animation V/ljh: currentValue = 0.37109637
2020-08-22 15:39:57.651 5471-5471/com.example.new_animation V/ljh: currentValue = 0.395532
2020-08-22 15:39:57.667 5471-5471/com.example.new_animation V/ljh: currentValue = 0.42178285
2020-08-22 15:39:57.684 5471-5471/com.example.new_animation V/ljh: currentValue = 0.44825655
2020-08-22 15:39:57.702 5471-5471/com.example.new_animation V/ljh: currentValue = 0.47330922
2020-08-22 15:39:57.718 5471-5471/com.example.new_animation V/ljh: currentValue = 0.5
2020-08-22 15:39:57.735 5471-5471/com.example.new_animation V/ljh: currentValue = 0.5266908
2020-08-22 15:39:57.751 5471-5471/com.example.new_animation V/ljh: currentValue = 0.55174345
2020-08-22 15:39:57.768 5471-5471/com.example.new_animation V/ljh: currentValue = 0.57821715
2020-08-22 15:39:57.785 5471-5471/com.example.new_animation V/ljh: currentValue = 0.6044678
2020-08-22 15:39:57.801 5471-5471/com.example.new_animation V/ljh: currentValue = 0.6289036
2020-08-22 15:39:57.818 5471-5471/com.example.new_animation V/ljh: currentValue = 0.65450853
2020-08-22 15:39:57.835 5471-5471/com.example.new_animation V/ljh: currentValue = 0.67967266
2020-08-22 15:39:57.852 5471-5471/com.example.new_animation V/ljh: currentValue = 0.7028899
2020-08-22 15:39:57.868 5471-5471/com.example.new_animation V/ljh: currentValue = 0.7269952
2020-08-22 15:39:57.885 5471-5471/com.example.new_animation V/ljh: currentValue = 0.75045335
2020-08-22 15:39:57.903 5471-5471/com.example.new_animation V/ljh: currentValue = 0.7718804
2020-08-22 15:39:57.918 5471-5471/com.example.new_animation V/ljh: currentValue = 0.7938927
2020-08-22 15:39:57.934 5471-5471/com.example.new_animation V/ljh: currentValue = 0.81506693
2020-08-22 15:39:57.952 5471-5471/com.example.new_animation V/ljh: currentValue = 0.83417606
2020-08-22 15:39:57.968 5471-5471/com.example.new_animation V/ljh: currentValue = 0.8535534
2020-08-22 15:39:57.985 5471-5471/com.example.new_animation V/ljh: currentValue = 0.8719225
2020-08-22 15:39:58.004 5471-5471/com.example.new_animation V/ljh: currentValue = 0.88824326
2020-08-22 15:39:58.020 5471-5471/com.example.new_animation V/ljh: currentValue = 0.9045085
2020-08-22 15:39:58.034 5471-5471/com.example.new_animation V/ljh: currentValue = 0.91962016
2020-08-22 15:39:58.051 5471-5471/com.example.new_animation V/ljh: currentValue = 0.9327506
2020-08-22 15:39:58.068 5471-5471/com.example.new_animation V/ljh: currentValue = 0.94550323
2020-08-22 15:39:58.084 5471-5471/com.example.new_animation V/ljh: currentValue = 0.9569855
2020-08-22 15:39:58.102 5471-5471/com.example.new_animation V/ljh: currentValue = 0.9666023
2020-08-22 15:39:58.117 5471-5471/com.example.new_animation V/ljh: currentValue = 0.97552824
2020-08-22 15:39:58.134 5471-5471/com.example.new_animation V/ljh: currentValue = 0.98309815
2020-08-22 15:39:58.152 5471-5471/com.example.new_animation V/ljh: currentValue = 0.9889647
2020-08-22 15:39:58.168 5471-5471/com.example.new_animation V/ljh: currentValue = 0.99384415
2020-08-22 15:39:58.185 5471-5471/com.example.new_animation V/ljh: currentValue = 0.9973154
2020-08-22 15:39:58.202 5471-5471/com.example.new_animation V/ljh: currentValue = 0.9992871
2020-08-22 15:39:58.217 5471-5471/com.example.new_animation V/ljh: currentValue = 1.0
从打印日志的值我们就可以看出,ValueAnimator确实已经在正常工作了,值在1000毫秒的时间内从0平滑过渡到了1,而这个计算工作就是由ValueAnimator帮助我们完成的。
除此之外,我们还可以调用setStartDelay方法来设置动画延迟播放的时间,调用setRepeatCount和setRepeatMode方法来设置动画循环播放的次数以及循环播放的模式,循环模式包括RESTART和REVERSE两种,分别表示重新播放和倒序播放的意思。
四.ObjectAnimator
ObjectAnimator是可以直接对任意对象的任意属性进行动画操作的.它虽然继承于ValueAnimator,底层的动画实现机制也是基于ValueAnimator来完成的。但是它比ValueAnimator更常用。
1.透明度
button.setOnClickListener {var anim = ObjectAnimator.ofFloat(textView,"alpha",1f,0.5f,1f)
anim.duration = 1000
anim.start()
}
这里就可以让textView控件的透明度由100%变为50%再变为100%。
第一个参数要求传入一个object对象,我们想要对哪个对象进行动画操作就传入什么,这里我传入了一个textview。第二个参数是想要对该对象的哪个属性进行动画操作,由于我们想要改变TextView的不透明度,因此这里传入"alpha"。后面的参数就是不固定长度了,想要完成什么样的动画就传入什么值,这里传入的值就表示将TextView从常规变换成半透明,再从半透明变换成常规。
2.旋转
button.setOnClickListener {var anim = ObjectAnimator.ofFloat(textView,"rotation",0f,360f)
anim.duration = 1000
anim.start()
}
3.移动
button.setOnClickListener {val X = textView.translationX
var anim = ObjectAnimator.ofFloat(textView,"translationX",X,-500f,X)
anim.duration = 1000
anim.start()
}
4.缩放
button.setOnClickListener {var anim = ObjectAnimator.ofFloat(textView,"scaleY",1f,5f,0.2f,1f)
anim.duration = 1000
anim.start()
}
5.总结
ofFloat()方法的第二个参数到底可以传哪些值呢?目前我们使用过了alpha、rotation、translationX和scaleY这几个值,分别可以完成淡入淡出、旋转、水平移动、垂直缩放这几种动画,那么还有哪些值是可以使用的呢?其实这个问题的答案非常玄乎,就是我们可以传入任意的值到ofFloat()方法的第二个参数当中。
因为ObjectAnimator在设计的时候就没有针对于View来进行设计,而是针对于任意对象的,它所负责的工作就是不断地向某个对象中的某个属性进行赋值,然后对象根据属性值的改变再来决定如何展现出来。此对象需要根据某个属性值的改变来不断刷新界面的显示,从而达到动画的效果。
ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法。
五.AnimatorSet
实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个**play()**方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim)
使用示例
button.setOnClickListener {var a1 = ObjectAnimator.ofFloat(textView,"alpha",1f,0f,1f)
var a2 = ObjectAnimator.ofFloat(textView,"rotation",0f,180f,0f)
var a3 = ObjectAnimator.ofFloat(textView,"translationX",0f,100f)
var a = AnimatorSet()
a.play(a1).with(a2).after(a3)
a.duration = 1000
a.start()
}
这里就是先执行a3,后执行a1和a2
六.Animator监听器
一般情况下
button.setOnClickListener {var anim = ObjectAnimator.ofFloat(textView,"alpha",1f,0f,1f)
anim.addListener(object :Animator.AnimatorListener{
override fun onAnimationRepeat(animation: Animator?) {
TODO("Not yet implemented")
}
override fun onAnimationEnd(animation: Animator?) {
TODO("Not yet implemented")
}
override fun onAnimationCancel(animation: Animator?) {
TODO("Not yet implemented")
}
override fun onAnimationStart(animation: Animator?) {
TODO("Not yet implemented")
}
})
}
但是也许很多时候我们并不想要监听那么多个事件,可能我只想要监听动画结束这一个事件,那么每次都要将四个接口全部实现一遍就显得非常繁琐。没关系,为此Android提供了一个适配器类,叫作AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:
addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果我想监听动画结束这个事件,就只需要单独重写这一个方法就可以了
button.setOnClickListener {var anim = ObjectAnimator.ofFloat(textView,"alpha",1f,0f,1f)
anim.addListener(object : AnimatorListenerAdapter(){
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
}
})
}