Android 属性动画与硬件加速

1、属性动画

  • 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()
    

先加速后减速: 屏幕内两个点移动

加速: 从屏幕内移动到屏幕外

减速: 从屏幕外移动到屏幕内

  • 1.7、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)
    }
}

2、硬件加速

普通的绘制就是利用 CPU 来计算颜色值, 然后绘制, 而所谓的硬件加速是 GPU 来绘制

缺点: 兼容性, GPU 只能绘制简单的图形, 比如 矩形,

3、离屏缓冲

  • 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)
  • 3.3 关闭硬件加速

开启硬件加速:

关闭离屏缓冲之后会自动切换到硬件
setLayerType(LAYER_TYPE_NONE, null)

用 setLayerType(LAYER_TYPE_HARDWARE, null) 会开启硬件加速, 但是同时也会开启一个硬件的离屏缓冲

关闭硬件加速:

setLayerType(LAYER_TYPE_SOFTWARE, null)
  • 3.4 硬件加速关于动画

只能用于简单的动画, 比如 translationX 等

view.animate()
        .translationX(200F)
        // 硬件加速
        .withLayer()
        .start()

你可能感兴趣的:(android,kotlin,自定义控件)