Kotlin自定义运动的路径---PathMeasure带来美丽

本文介绍了如何利用Kotlin的PathMeasure类来创建自定义动画。通过PathMeasure,可以测量Path的长度和获取路径上的任意点,进而实现如图所示的圆形运动效果,用lineTo方法将路径点连贯起来。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一,图片:
这里写图片描述

我们需要知道PathMeasure这个类,它能够从新测量我们的Path路径,例如获取到Path路径的长度以及路径的开始和结束为止。这样如图所示,我们可以画出一个圆,在圆结尾的点获取这个点,通过linto进行连接。

package com.example.ls.pathmeasure

import android.animation.Animator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.os.Handler
import android.os.Message
import android.util.Log
import android.view.View
import java.lang.ref.WeakReference
import java.lang.reflect.Array.getLength
import java.lang.reflect.Array.getLength


/**
 *作者:王飞
 *邮箱:1276998208@qq.com
 *create on 2018/7/20 11:09
 */
class CustomView : View {
    private lateinit var circle_outside_path: Path
    private lateinit var circle_inside_path: Path
    private lateinit var mPaint: Paint
    private var mViewWidth: Int = 0//原始数据类型不能lateinit修饰
    private var mViewHeight: Int = 0
    private lateinit var measure: PathMeasure
    private lateinit var mUpdateListener: ValueAnimator.AnimatorUpdateListener;
    private var mAnimaltorValue: Float = 0.0f;
    private lateinit var mAnimaltorListenner: Animator.AnimatorListener
    private lateinit var animtorHandler: Handler
    private lateinit var mStartingAnimator: ValueAnimator
    private lateinit var mSearchingAnimator: ValueAnimator
    private lateinit var mEndingAnimator: ValueAnimator
    // 当前的状态(非常重要)
    public var mCurrentState = State.NONE

    // 这个视图拥有的状态
    enum class State {
        NONE,
        STARTING,
        SEARCHING,
        ENDING
    }

    private var count: Int = 0

    // 判断是否已经搜索结束
    public var isOver = false

    constructor(context: Context) : super(context) {
        initPaint()//初始化画笔
        initPath()//初始化路径
        initAnimalLisenner()//初始化监听
        initHandler()
        initAnimaltor()
        // 进入开始动画
        mCurrentState = State.STARTING
        //刚进入动画
        mStartingAnimator.start()

    }

    private fun initPaint() {
        mPaint = Paint()
        mPaint.style = Paint.Style.STROKE
        mPaint.color = Color.WHITE
        mPaint.strokeWidth = 16f
    }


    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mViewWidth = w
        mViewHeight = h
    }


    private fun initAnimalLisenner() {
        mUpdateListener = ValueAnimator.AnimatorUpdateListener { animation ->
            mAnimaltorValue = animation.animatedValue as Float//0-1
            invalidate()
        }
        mAnimaltorListenner = object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {

            }

            override fun onAnimationEnd(animation: Animator) {
                //这里动画结束监听。
                val message = Message.obtain()
                message.what = 1001
                animtorHandler.sendMessage(message);

            }

            override fun onAnimationCancel(animation: Animator) {

            }

            override fun onAnimationRepeat(animation: Animator) {

            }
        }

    }


    private fun initHandler() {
        animtorHandler = object : Handler() {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                when (mCurrentState) {
                    State.STARTING -> {
                        // 从开始动画转换好搜索动画
                        isOver = false
                        mCurrentState = State.SEARCHING
                        mStartingAnimator.removeAllListeners()
                        mSearchingAnimator.start()
                    }
                    State.SEARCHING -> if (!isOver) {  // 如果搜索未结束 则继续执行搜索动画
                        mSearchingAnimator.start()
                        count++
                        if (count > 2) {       // count大于2则进入结束状态
                            isOver = true
                        }
                    } else {        // 如果搜索已经结束 则进入结束动画
                        mCurrentState = State.ENDING
                        mEndingAnimator.start()
                    }
                    State.ENDING ->
                        // 从结束动画转变为无状态
                        mCurrentState = State.NONE
                }
            }
        }
    }


    private fun initAnimaltor() {
        mStartingAnimator = ValueAnimator.ofFloat(0F, 1F).setDuration(2000)
        mSearchingAnimator = ValueAnimator.ofFloat(0F, 1F).setDuration(2000);
        mEndingAnimator = ValueAnimator.ofFloat(0F, 1F).setDuration(2000);
        mStartingAnimator.addUpdateListener(mUpdateListener)
        mSearchingAnimator.addUpdateListener(mUpdateListener);
        mEndingAnimator.addUpdateListener(mUpdateListener);


        mStartingAnimator.addListener(mAnimaltorListenner)
        mSearchingAnimator.addListener(mAnimaltorListenner);
        mEndingAnimator.addListener(mAnimaltorListenner);
    }

    private fun initPath() {
        circle_inside_path = Path()
        circle_outside_path = Path()

        measure = PathMeasure()
        //内画圆
        val rectF = RectF(-50f, -50f, 50f, 50f)
        val rectF1 = RectF(-100f, -100f, 100f, 100f)
        //画弧度
        circle_inside_path.addArc(rectF, 45f, 357f)
        circle_outside_path.addArc(rectF1, 45f, 357f)
        val pos = FloatArray(2)
        measure.setPath(circle_outside_path, false)//把圆弧到这个测量里面用来获取把守位置
        measure.getPosTan(0f, pos, null)//获得把守位置
        //画把守的线
        circle_inside_path.lineTo(pos[0], pos[1])
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.translate((mViewWidth / 2).toFloat(), (mViewHeight / 2).toFloat())
        canvas.drawColor(Color.parseColor("#0082D7"))

        when (mCurrentState) {
            State.NONE -> canvas.drawPath(circle_inside_path, mPaint);
            State.STARTING -> {
                measure.setPath(circle_inside_path, false)
                val dst = Path()
                measure.getSegment(measure.getLength() * mAnimaltorValue, measure.getLength(), dst, true);
                canvas.drawPath(dst, mPaint);
            }
            State.SEARCHING -> {
                measure.setPath(circle_inside_path, false)
                val dst2 = Path()
                val stop = measure.getLength() * mAnimaltorValue
                val start = (stop - (0.5F - Math.abs(mAnimaltorValue - 0.5F)) * 200F) as Float
                measure.getSegment(start, stop, dst2, true)
                canvas.drawPath(dst2, mPaint)
            }
            State.ENDING -> {
                measure.setPath(circle_inside_path, false)
                val dst3 = Path()
                measure.getSegment(0F,measure.getLength() * mAnimaltorValue, dst3, true)
                canvas.drawPath(dst3, mPaint)
            }
        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值