安卓自定义动画
2020-09-20 本文已影响0人
爱写代码的小王子
本篇简书主要总结一下今天学习自定义动画效果的知识点,学习内容主要包括
- 1.补间动画和属性动画的区别
- 2.属性动画的实现流程
- 3.如何控制动画播放的顺序
- 4.最后实现一个小demo来实战
学习自定义动画,首先需要了解补间动画和属性动画的相关概念,补间动画和属性动画的区别:
- 补间动画,即
Tween动画,这种动画的优点是使用起来简单,一般使用xml文件的方式编写,动画形式包括:alpha(淡入淡出),scale(缩放),translate(平移),rotate(旋转),缺点是动画形式单一,要么实现单个动画效果,要么实现组合动画效果,但是无法支持自定义View的扩展,而且它的动画不具有交互性,也就是说动画没有改变控件本身的属性 - 属性动画,即
ObjectAnimator,这种动画不仅包含补间动画的全部功能,而且可用支持自定义View的扩展,说到这里就必须数值发生器ValueAnimator,正是由于这个数值发生器,不断生成变化的数值,当然这个数值可以是Float类型,也可以是Int类型,才实现控件属性的变化,这也是接下来实战时主要用到的知识点。
动画属性
属性动画的实现流程,如图所示
image.png
如何控制动画播放的顺序
实现想要的动画效果,首先需要分析由那些部分构成,然后分析它们之间关系(位置或者大小等),然后才去实现对应的动画效果,最后组合成自己想要的效果,控制动画播放的顺序可以使用属性动画集AnimatorSet,可以实现复杂的组合动画,既可以同时对多个对象做动画并控制执行顺序,也可以控制单个对象的动画执行顺序。
AnimatorSet的常用方法
-
playTogether()同时播放所有动画 -
playSequentially()顺序播放所有动画
最后进入我们的demo实战
效果
image.png
原理
通过属性动画里的值变化器ValueAniamtor,不断改变左边扇形绘制的起始角度,获取到的改变值,不断刷新重绘,然后赋值给绘制时对应的起始角度和终止角度,实现吞吐效果,右边小球同理,改变小圆中心点的横坐标cx,然后不断重绘,实现向左边移动效果
创建一个类,继承View
class MouseLoading : View {
}
分析两个控件之间的位置关系,设定右边小圆半径为r,左边扇形半径为3r,两者间距为0.5r,所以控件宽度一共是8.5r的大小,控件对应高度为6r,下面判断的是当xml里所给控件宽度大于高度时,仍需另外判断是否控件宽度足够8.5r的大小
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
//确定小球的半径
if (width >= height) {
//高度顶满
ballRadius = height / 6f
//判断宽度能否容纳8.5个R
if (8.5 * ballRadius > width) {
ballRadius = width / 8.5f
}
} else {
//宽度顶满
ballRadius = width / 8.5f
}
mouseRadius = 3 * ballRadius
space = 0.5f * ballRadius
//确定中心点坐标
cx = ((width - 8.5 * ballRadius) / 2f + 3 * ballRadius).toFloat()
cy = height / 2f
}
值动画的创建
//创建动画
private fun createAnim() {
if (mouseMoveAnim == null) {
//张嘴闭嘴动画
mouseMoveAnim = ValueAnimator.ofFloat(0f, 45f, 0f).apply {
duration = 650
repeatCount = ValueAnimator.INFINITE
addUpdateListener {
//获取当前变化产生的值 0-45
mouseAngle = it.animatedValue as Float
//重新绘制自己 -> onDraw()
invalidate()
}
}
}
if (ballMoveAnim == null) {
ballMoveAnim = ValueAnimator.ofFloat(0f, 4.5f * ballRadius).apply {
duration = 650
repeatCount = ValueAnimator.INFINITE
addUpdateListener {
ballTranslateX = it.animatedValue as Float
invalidate()
}
}
}
//顺序执行
//playSequentially(mouseMoveAnim,ballMoveAnim)
//同时执行
animators.playTogether(mouseMoveAnim, ballMoveAnim)
}
上面的mouseMoveAnim,ballMoveAnim分别用来接收两个值动画对象,animators则是组合动画AnimatorSet()的对象
//定义一个变量保存动画对象
private var ballMoveAnim: ValueAnimator? = null
private var mouseMoveAnim: ValueAnimator? = null
//动画集
private val animators = AnimatorSet()
最后绘制控件
/**
创建对象
复杂的计算
不要放在onDraw
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onDraw(canvas: Canvas?) {
//绘制圆弧
canvas?.drawArc(
cx - mouseRadius, cy - mouseRadius,
cx + mouseRadius, cy + mouseRadius,
mouseAngle, 360f - 2 * mouseAngle,
true,
mPaint
)
//绘制圆形
canvas?.drawCircle(cx + 4.5f * ballRadius - ballTranslateX, cy, ballRadius, mPaint)
}
总结:学习过程需要不断总结,自己不会的东西还很多,今天布置的作业实现下载动画,我会在后面的简书里发出来。