1.1、ViewPropertyAnimator
/**
* 最简单的动画,只能 平移,旋转,缩放等简单的
*/
private fun animation() {
view.animate()
.translationX(dp2px(200F))
.translationY(dp2px(200F))
.scaleX(1.5F)
.scaleY(1.5F)
.rotation(300F)
.setDuration(1_000)
.setStartDelay(1_000)
.start()
}
1.2、ObjectAnimator
ObjectAnimator.ofFloat(view, "mRadius", dp2px(0F), dp2px(100F))
.setDuration(1_000)
.start()
这里 view 里面需要有一个 setMRadius 方法, 因为属性动画会一直调用该方法, 用来刷新属性
在 setXXX 方法里面需要手动调用 invalidate(), 因为只是改变了变量值, 并没有通知 view 刷新控件
1.3、AnimatorSet
val topFlipAnimator = ObjectAnimator.ofFloat(view, "topFlip", 0F, -30F)
.setDuration(1_000)
val bottomFlipAnimator = ObjectAnimator.ofFloat(view, "bottomFlip", 0F, 30F)
.setDuration(1_000)
val flipRotationAnimator = ObjectAnimator.ofFloat(view, "flipRotation", 0F, 270F)
.setDuration(1_000)
AnimatorSet().apply {
startDelay = 1_000
playSequentially(bottomFlipAnimator, flipRotationAnimator, topFlipAnimator)
start()
}
1.4、PropertyValuesHolder
多个属性同时操作
val bottomFlipHolder = PropertyValuesHolder.ofFloat("bottomFlip", 0F, 30F)
val topFlipHolder = PropertyValuesHolder.ofFloat("topFlip", 0F, 30F)
val flipRotationHolder = PropertyValuesHolder.ofFloat("flipRotation", 0F, 270F)
ObjectAnimator.ofPropertyValuesHolder(view, bottomFlipHolder, topFlipHolder, flipRotationHolder)
.apply {
startDelay = 1_000
duration = 1_000
start()
}
1.5、Keyframe
同一个 view 的同一个属性 不同阶段
val targetTranslationX = dp2px(200F)
val keyframe1 = Keyframe.ofFloat(0F, 0F)
val keyframe2 = Keyframe.ofFloat(0.1F, 1.5F * targetTranslationX)
val keyframe3 = Keyframe.ofFloat(0.9F, 0.6F * targetTranslationX)
val keyframe4 = Keyframe.ofFloat(1.0F, 1.0F * targetTranslationX)
val translationXHolder = PropertyValuesHolder.ofKeyframe("translationX", keyframe1, keyframe2, keyframe3, keyframe4)
ObjectAnimator.ofPropertyValuesHolder(view, translationXHolder)
.apply {
startDelay = 1_000
duration = 2_000
start()
}
1.6、Interpolator
速度模型
view.animate()
.translationX(dp2px(200F))
.setInterpolator(LinearInterpolator())
.setDuration(1_000)
.setStartDelay(1_000)
.start()
先加速后减速: 屏幕内两个点移动
加速: 从屏幕内移动到屏幕外
减速: 从屏幕外移动到屏幕内
TypeEvaluator
估值器估值器是指当动画进行到 10% 的时候, 值是多少,进行到 20% 的时候, 值是多少
基本数据类型有默认的估值器, 如果是别的对象比如 PointF() 就需要自己来写估值器
private fun typeEvaluator() {
val start = PointF(0F, 0F)
val des = PointF(dp2px(200F), dp2px(300F))
val animator = ObjectAnimator.ofObject(view, "mPointF", PointFEvaluator(), start, des)
animator.duration = 1_000
animator.startDelay = 1_000
animator.start()
}
class PointFEvaluator : TypeEvaluator {
override fun evaluate(fraction: Float, startValue: PointF?, endValue: PointF?): PointF {
val x = (startValue?.x ?: 0F) + ((endValue?.x ?: 0F) - (startValue?.x ?: 0F)) * fraction
val y = (startValue?.y ?: 0F) + ((endValue?.y ?: 0F) - (startValue?.y ?: 0F)) * fraction
return PointF(x, y)
}
}
普通的绘制就是利用 CPU
来计算颜色值, 然后绘制, 而所谓的硬件加速是 GPU
来绘制
缺点: 兼容性, GPU
只能绘制简单的图形, 比如 矩形
, 圆
等
3.1、OffScreenBuffer
就是单独绘制 View 的一个区域, 为了让绘制过程不收到干扰, 或者在做动画的时候, 把某一块区域单独拿出来性能会更好
canvas.saveLayer() 保存状态, 而且还拉出来一个层
但是 saveLayer() 太重了, Google 不推荐这么做
3.2 setLayerType()
这个最好不要写在 onDraw() 里面, 因为会引起刷新
1、使用软件的方式离屏缓冲
setLayerType(LAYER_TYPE_SOFTWARE, null)
2、使用硬件的方式离屏缓冲
setLayerType(LAYER_TYPE_HARDWARE, null)
3、不用离屏缓冲
setLayerType(LAYER_TYPE_NONE, null)
开启硬件加速:
关闭离屏缓冲之后会自动切换到硬件
setLayerType(LAYER_TYPE_NONE, null)
用 setLayerType(LAYER_TYPE_HARDWARE, null) 会开启硬件加速, 但是同时也会开启一个硬件的离屏缓冲
关闭硬件加速:
setLayerType(LAYER_TYPE_SOFTWARE, null)
只能用于简单的动画, 比如 translationX 等
view.animate()
.translationX(200F)
// 硬件加速
.withLayer()
.start()