安卓自定义动画

2020-09-20  本文已影响0人  爱写代码的小王子

本篇简书主要总结一下今天学习自定义动画效果的知识点,学习内容主要包括

学习自定义动画,首先需要了解补间动画和属性动画的相关概念,补间动画和属性动画的区别:

属性动画的实现流程,如图所示


image.png

如何控制动画播放的顺序
实现想要的动画效果,首先需要分析由那些部分构成,然后分析它们之间关系(位置或者大小等),然后才去实现对应的动画效果,最后组合成自己想要的效果,控制动画播放的顺序可以使用属性动画集AnimatorSet,可以实现复杂的组合动画,既可以同时对多个对象做动画并控制执行顺序,也可以控制单个对象的动画执行顺序。
AnimatorSet的常用方法

最后进入我们的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)

    }

上面的mouseMoveAnimballMoveAnim分别用来接收两个值动画对象,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)
    }

总结:学习过程需要不断总结,自己不会的东西还很多,今天布置的作业实现下载动画,我会在后面的简书里发出来。

上一篇 下一篇

猜你喜欢

热点阅读