一个未选中圆形矩形,一个选中矩形,一个开关按钮,点击的时候开启滑动动画即可
效果
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)
}
}