欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

kotlin的自定义动画

程序员文章站 2022-03-09 17:22:14
AnroidStudio中使用kotlin语言的自定义动画第一个练习,后面还会更新第二练习1.动画效果:开始点击start后,小球开始进入大球的嘴里,点击stop后,停止动画(还不知道哪个软件录制gif好,下去再搜, 现在只能口述了)2.主题思路分析:/*拆分为多个部分寻找关系每个部分的绘制寻找动画因子创建动画*/详细:拆分为多个部分: 嘴巴和小球寻找关系:大小 间距 位置,可以根据自己的要求设置每个部分的绘制:onDraw方法画笔paint 画布 canva...

AnroidStudio中使用kotlin语言的自定义动画
第一个练习,后面还会更新第二练习
1.动画效果:
开始
kotlin的自定义动画
点击start后,小球开始进入大球的嘴里,
kotlin的自定义动画

点击stop后,停止动画
(还不知道哪个软件录制gif好,下去再搜, 现在只能口述了)

2.主题思路分析:
/*

拆分为多个部分
寻找关系
每个部分的绘制
寻找动画因子
创建动画

*/
详细:
拆分为多个部分: 嘴巴和小球

寻找关系:大小 间距 位置,可以根据自己的要求设置
kotlin的自定义动画

每个部分的绘制:
onDraw方法
画笔paint 画布 canvas 使用canvas.draw

寻找动画因子:
观察这个动画中什么在变
嘴的动画因子是开始的度数和最后度数的变化
小球的动画因子是圆心的x坐标

创建动画:
使用的是,ValueAnimator.ofFloat ,得到变化的一系列值
设置动画属性: duration repeat
监听值的变化,得到回调,同时使用invalidate,调用onDraw
动画调用的效果, 以及动画的播放、暂停、取消

3.代码:
3.1 先画出图形
自己定义的kotln的class代码

class MouseAnim: View {
    // 定义画笔, 只有在需要使用的时候才定义,使用懒加载
    // 懒加载使用的是val 不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)
    private val mPaint: Paint  by lazy {
        Paint().apply {
            color = Color.BLUE
            style = Paint.Style.FILL
        }
    }

    // 定义小球的半径
    private var bollRadius = 0f
    // 定义嘴巴的半径
    private var mouseRadius = 0f
    // 两者之间的距离
    private var span = 0f
    // 嘴巴的x坐标
    private var cx = 0f
    // 嘴巴的y坐标
    private var cy = 0f

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        if (width >= height){
            bollRadius = height/6f
            if (bollRadius*8.5f > width){
                bollRadius = width/8.5f
            }
        }else{
            bollRadius = width/8.5f
        }

        mouseRadius = bollRadius*3f
        span = 0.5f*bollRadius
        cx = (width-bollRadius*8.5f)+mouseRadius
        cy = height/2f

    }
    // 两种构造方法
    // 代码
    constructor(context: Context) :super(context){}
    // xml
    constructor(context: Context, attributeSet: AttributeSet): super(context, attributeSet){}

    override fun onDraw(canvas: Canvas?) {
        canvas?.drawArc(cx-mouseRadius, cy-mouseRadius, cx+mouseRadius, cy+mouseRadius, 45f, 270f, true,mPaint)

        canvas?.drawCircle(cx+4.5f*bollRadius, height/2f, bollRadius, mPaint)
    }
}

对应的xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.android.mymouselodinganimationauto1.MouseAnim
        android:id="@+id/mouseView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

kotlin的自定义动画

运行结果:

3.2在上述代码中添加动画
kotlin代码

class MouseAnim: View {
    // 定义画笔, 只有在需要使用的时候才定义,使用懒加载
    // 懒加载使用的是val 不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)
    private val mPaint: Paint  by lazy {
        Paint().apply {
            color = Color.BLUE
            style = Paint.Style.FILL
        }
    }

    // 定义小球的半径
    private var bollRadius = 0f
    // 定义嘴巴的半径
    private var mouseRadius = 0f
    // 两者之间的距离
    private var span = 0f
    // 嘴巴的x坐标
    private var cx = 0f
    // 嘴巴的y坐标
    private var cy = 0f
    // 嘴巴的动画
    private var mouseMoveView: ValueAnimator? = null
    // 小球的动画
    private var bollMoveView: ValueAnimator? = null
    // 两个动画需要同时动, 因此需要一个集合
    private var allAnim = AnimatorSet()

    // 找出动画因子
    // 嘴的动画因子
    private var mouseAngle = 0f
    // 小球的动画因子
    private var bollTransX = 0f

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        if (width >= height){
            bollRadius = height/6f
            if (bollRadius*8.5f > width){
                bollRadius = width/8.5f
            }
        }else{
            bollRadius = width/8.5f
        }

        mouseRadius = bollRadius*3f
        span = 0.5f*bollRadius
        cx = (width-bollRadius*8.5f)/2f+mouseRadius
        cy = height/2f

    }
    // 两种构造方法
    // 代码
    constructor(context: Context) :super(context){}
    // xml
    constructor(context: Context, attributeSet: AttributeSet): super(context, attributeSet){}

    override fun onDraw(canvas: Canvas?) {
        canvas?.drawArc(cx-mouseRadius, cy-mouseRadius, cx+mouseRadius, cy+mouseRadius, mouseAngle, 360f-2f*mouseAngle, true,mPaint)

        canvas?.drawCircle(cx+4.5f*bollRadius-bollTransX, height/2f, bollRadius, mPaint)
    }

    private fun createView(){
        if (mouseMoveView == null) {
            mouseMoveView = ValueAnimator.ofFloat(0f, 45f, 0f).apply {
                duration = 680
                repeatCount = ValueAnimator.INFINITE
                addUpdateListener {
                    mouseAngle = it.animatedValue as Float
                    invalidate()
                }
            }
        }

        if (bollMoveView == null) {
            bollMoveView = ValueAnimator.ofFloat(0f, 4.5f * bollRadius, 0f).apply {
                duration = 680
                repeatCount = ValueAnimator.INFINITE
                addUpdateListener {
                    bollTransX = it.animatedValue as Float
                    invalidate()
                }
            }
        }

        allAnim.apply {
            playTogether(mouseMoveView, bollMoveView)
        }
    }
    fun startAnim(){
        createView()
        if (allAnim.isPaused){
            allAnim.resume()
        }else{
            allAnim.start()
        }
    }

    fun stopAnim(){
        allAnim.pause()
    }
}

对应的xml代码,添加了两个button

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    tools:context=".MainActivity">

    <com.android.mymouselodinganimationauto1.MouseAnim
        android:id="@+id/mouseView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/mStop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/mStart"
        app:layout_constraintTop_toTopOf="@+id/mStart" />

    <Button
        android:id="@+id/mStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:text="start"
        app:layout_constraintEnd_toStartOf="@+id/mStop"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/mouseView" />

</androidx.constraintlayout.widget.ConstraintLayout>

在MainActivity里面的代码,按钮监听事件

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // view是指自己创建的类的id值
        mStart.setOnClickListener {
            mouseView.startAnim()
        }
        mStop.setOnClickListener {
            mouseView.stopAnim()
        }
    }
}

4.最后的运行
kotlin的自定义动画
5.整体的结构目录
kotlin的自定义动画

本文地址:https://blog.csdn.net/weixin_44614751/article/details/108701795