android自定义开关按钮

一个未选中圆形矩形,一个选中矩形,一个开关按钮,点击的时候开启滑动动画即可

效果在这里插入图片描述
在这里插入图片描述

import android.animation.Animator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.icu.util.Measure
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import com.pansy.sakura.R
import com.pansy.sakura.util.AlgorithmUtil
import com.pansy.sakura.util.LogUtil
import com.pansy.sakura.util.dp2px
import kotlinx.coroutines.selects.select
import kotlin.math.min

class CustomSwitchButton: View {
    
    
    private val SB_WIDTH=160f
    private val SB_HEIGHT=70f
    private var mUnSelectBackGroundColor=Color.parseColor("#f2f2f2")//未选择背景颜色
    private var mSelectBackGroundColor=Color.GREEN//选择背景颜色
    private var mIsSelect=false//开关状态
    private var mIsAnimating=false//是否动画中
    private var mValue=0f
    private val ANIMATION_DURATIONS=500L
    private var BUTTON_MARGIN=6//按钮margin
    private var mBgPaint=Paint()
    private var mSelectBgPaint=Paint()
    private var mBtnPaint=Paint()

    constructor(context: Context) : super(context) {
    
    

    }

    constructor(context: Context, attrs: AttributeSet):this(context,attrs,0){
    
    

    }

    constructor(context: Context, attrs: AttributeSet, defStyle:Int):this(context,attrs,defStyle,0){
    
    

    }

    constructor(context: Context, attrs: AttributeSet, defStyle:Int, defRes:Int):super(context,attrs,defStyle,defRes){
    
    
        initView(context,attrs)
    }

    private fun initView(context: Context, attrs: AttributeSet){
    
    
        isClickable=true

        val ta=context.obtainStyledAttributes(attrs, R.styleable.CustomSwitchButton)
        mUnSelectBackGroundColor=ta.getColor(R.styleable.CustomSwitchButton_sb_unselect_background,Color.GRAY)
        mSelectBackGroundColor=ta.getColor(R.styleable.CustomSwitchButton_sb_select_background,Color.GREEN)
        ta.recycle()

        mBgPaint.style=Paint.Style.FILL
        mBgPaint.color=mUnSelectBackGroundColor

        mSelectBgPaint.style=Paint.Style.FILL
        mSelectBgPaint.color=mSelectBackGroundColor

        mBtnPaint.style=Paint.Style.FILL
        mBtnPaint.color=Color.WHITE

    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    
    
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(SB_WIDTH.toInt(),SB_HEIGHT.toInt())
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
    
    
        super.onLayout(changed, left, top, right, bottom)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
    
    
        if(event==null) return super.onTouchEvent(event)

        if(event.action==MotionEvent.ACTION_UP){
    
    
            if(mIsAnimating) return false
            startAnimation()
            return true
        }

        return super.onTouchEvent(event)
    }

    fun setSelect(select:Boolean){
    
    
        if(select==mIsSelect) return
        startAnimation()
    }

    fun isSelect():Boolean{
    
    
        return mIsSelect

    }

    private fun startAnimation(){
    
    
        mIsAnimating=!mIsAnimating
        lateinit var va:ValueAnimator
        if(mIsSelect){
    
    
            va=ValueAnimator.ofFloat(1f,0f)
        }else{
    
    
            va=ValueAnimator.ofFloat(0f,1f)
        }

        va.duration=ANIMATION_DURATIONS

        va.addUpdateListener {
    
    
            mValue=it.animatedValue as Float
            invalidate()
        }

        va.addListener(object:Animator.AnimatorListener{
    
    
            override fun onAnimationStart(animation: Animator?) {
    
    

            }

            override fun onAnimationEnd(animation: Animator?) {
    
    
                mIsAnimating=!mIsAnimating
                mIsSelect=!mIsSelect
                invalidate()
            }

            override fun onAnimationCancel(animation: Animator?) {
    
    

            }

            override fun onAnimationRepeat(animation: Animator?) {
    
    

            }

        })

        va.interpolator = DecelerateInterpolator()
        va.start()
    }

    override fun onDraw(canvas: Canvas?) {
    
    
        super.onDraw(canvas)
        if(canvas==null)  return

        var deltaX=SB_WIDTH-SB_HEIGHT//开关滑动的总距离

        val selectPath=Path()
        val rdii=AlgorithmUtil.formatRadiiFloatArray(floatArrayOf(SB_HEIGHT/2,SB_HEIGHT/2,SB_HEIGHT/2,SB_HEIGHT/2))
        val selectRoundRect= RectF(0f,0f,SB_WIDTH  ,SB_HEIGHT)
        selectPath.addRoundRect(selectRoundRect,rdii,Path.Direction.CW)
        canvas.clipPath(selectPath)

        //关状态背景
        val bgRect= RectF(0f,0f,SB_WIDTH,SB_HEIGHT)
        canvas.drawRoundRect(bgRect,SB_HEIGHT/2,SB_HEIGHT/2,mBgPaint)
        
        //开状态背景
        val selectBgRect= RectF(0f,0f,SB_WIDTH*mValue  ,SB_HEIGHT)
        canvas.drawRoundRect(selectBgRect,SB_HEIGHT/2,SB_HEIGHT/2,mSelectBgPaint)

        //开关按钮
        canvas.drawCircle(SB_HEIGHT/2+deltaX*mValue,SB_HEIGHT/2,SB_HEIGHT/2-BUTTON_MARGIN*2,mBtnPaint)

    }


}

猜你喜欢

转载自blog.csdn.net/a1663049254/article/details/130240905
今日推荐