val switch = findViewById<BaseSwitch>(R.id.switch_btn)
switch.onCheckedListener= {
Log.e("1111111111111", "是否点击${it}")
}
package com.lxt.ui.compnent.widget
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.util.Log
import android.view.View
import com.lxt.ui.compnent.R
import com.lxt.ui.compnent.extension.dp2px
import kotlin.math.abs
class BaseSwitch(context: Context, attrs: AttributeSet) : View(context, attrs),
View.OnClickListener {
protected var mWidth = 0
protected var mHeight = 0
//画笔
//底部背景
protected var paintTrack = Paint()
//可滚动部分
protected var paintThumb = Paint() //可滚动部分
//对应颜色(打开/关闭)
//底部颜色关
protected var trackColorOff = 0
//底部颜色开
protected var trackColorOn = 0
//可滚动部分颜色关
protected var thumbColorOff = 0
//可滚动部分颜色关
protected var thumbColorOn = 0
//边框
protected var strokeWidth = 10
//文字
protected var paintText: Paint = Paint()
protected var textOff: String?
protected var textOn: String?
protected var textSizeOff = 0
protected var textSizeOn = 0
protected var textColorOff = Color.WHITE //字体颜色
protected var textColorOn = Color.WHITE
protected var isShowText: Boolean = false //是否显示文字
protected var isChecked = false
//点击按钮回调
lateinit var onCheckedListener: (flag: Boolean) -> Unit
//动画
protected var animatorValue = 0f //动画变化的值
protected var animatorDuration = 0 //动画时间
protected var animatorValueOff = 10f //动画开始的值
protected var animatorValueOn = 0f //动画结束的值
protected var offTextX = 3
protected var trackRadius = 48 //背景 圆角
protected var trackHeight = 100//背景 高度
protected var thumbRadius = 40 //滑块 圆角
protected var thumbHeight = 80 //滑块 高度
protected var thumbWidth = 80//滑块 宽度
/**
* 初始化开关样式
*/
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.KButton)
trackColorOff = typedArray.getColor(R.styleable.BaseSwitch_track_color_off, Color.GRAY)
thumbColorOff = typedArray.getColor(R.styleable.BaseSwitch_thumb_color_off, Color.WHITE)
textColorOff = typedArray.getColor(R.styleable.BaseSwitch_text_color_off, Color.WHITE)
textSizeOff = typedArray.getDimensionPixelOffset(R.styleable.BaseSwitch_text_size_off, 10)
textOff = typedArray.getString(R.styleable.BaseSwitch_text_off)
if (textOff == null) {
textOff = "开"
}
strokeWidth = typedArray.getDimensionPixelOffset(
R.styleable.BaseSwitch_stroke_width,
context.dp2px(0)
)
//on
trackColorOn = typedArray.getColor(R.styleable.BaseSwitch_track_color_on, Color.BLUE)
thumbColorOn = typedArray.getColor(R.styleable.BaseSwitch_thumb_color_on, Color.WHITE)
textColorOn = typedArray.getColor(R.styleable.BaseSwitch_text_color_on, Color.WHITE)
textSizeOn = typedArray.getDimensionPixelOffset(R.styleable.BaseSwitch_text_size_off, 10)
textOn = typedArray.getString(R.styleable.BaseSwitch_text_on)
if (textOn == null) {
textOn = "关"
}
//其它属性
isShowText = typedArray.getBoolean(R.styleable.BaseSwitch_text_show, false)
isChecked = typedArray.getBoolean(R.styleable.BaseSwitch_checked, true)
animatorDuration = typedArray.getInteger(R.styleable.BaseSwitch_animator_duration, 300)
initPaint()
setOnClickListener(this)
}
/**
* 初始化画笔
*/
private fun initPaint() {
paintTrack.isAntiAlias = true
paintThumb.isAntiAlias = true
paintText.isAntiAlias = true
if (isChecked) {
setPaintOff()
} else {
setPaintOn()
}
}
/**
* 打开
*/
fun setPaintOff() {
paintTrack.color = trackColorOff
paintThumb.color = thumbColorOff
paintText.color = textColorOff
paintText.textSize = textSizeOff.toFloat()
}
/**
* 关闭
*/
fun setPaintOn() {
paintTrack.color = trackColorOn
paintThumb.color = thumbColorOn
paintText.color = textColorOn
paintText.textSize = textSizeOn.toFloat()
}
/**
* 是否选中操作
* @param isChecked
*/
private fun switchOperate(isChecked: Boolean) {
if (this.isChecked == isChecked) { //状态一样, 不处理
return
}
this.isChecked = isChecked
if (isChecked) {
checked()
startAnimator(animatorValueOff, mWidth - animatorValueOff - thumbHeight)
} else {
startAnimator(mWidth - animatorValueOff - thumbHeight, animatorValueOff)
unChecked()
}
onCheckedListener(isChecked)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
Log.e("11111111111", "宽:${measuredWidth}高:${measuredHeight}")
mWidth = measuredWidth
mHeight = measuredHeight
animatorValue = if (isChecked) animatorValueOff else animatorValueOn
}
override fun onClick(v: View?) {
switchOperate(!isChecked)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
drawTrack(canvas)
drawThumb(canvas)
}
/**
* 背景
* @param canvas
*/
private fun drawTrack(canvas: Canvas) {
Log.e("11111111", "${strokeWidth.toFloat()}")
val trackTop: Int = (mHeight - trackHeight) / 2
val trackBottom: Int = trackTop + trackHeight
canvas.drawRoundRect(
RectF(
strokeWidth.toFloat(),
(trackTop + strokeWidth).toFloat(),
(mWidth - strokeWidth).toFloat(),
(trackBottom - strokeWidth).toFloat()
), trackRadius.toFloat(), trackRadius.toFloat(), paintTrack
)
}
/**
* 滑块
* @param canvas
*/
private fun drawThumb(canvas: Canvas) {
Log.e("1111111", "mHeight${mHeight}" + "trackHeight${trackHeight}")
val thumbTop = (mHeight - thumbHeight) / 2
val thumbBottom = thumbTop + thumbHeight
Log.e("1111111", "center${animatorValue}")
canvas.drawRoundRect(
RectF(
animatorValue,
thumbTop.toFloat(),
(thumbHeight + animatorValue),
(thumbTop + thumbHeight).toFloat()
), thumbRadius.toFloat(), thumbRadius.toFloat(), paintThumb
)
}
/**
* 动画监听
* @param startValue 开始的值
* @param endValue 结束的值
*/
private fun startAnimator(startValue: Float, endValue: Float) {
val animator = ValueAnimator.ofFloat(startValue, endValue)
animator.addUpdateListener { animation ->
animatorValue = animation.animatedValue as Float
//判断是否超过中间值
if (abs(startValue - animatorValue) > abs(endValue - animatorValue)) { //超过一半
if (isChecked) {
setPaintOff()
} else {
setPaintOn()
}
}
//动画结束
if (animatorValue == endValue) {
animatorEnd()
}
//立即刷新(重新draw())
invalidate()
}
animator.duration = animatorDuration.toLong() //时间
animator.start()
}
//动画结束--执行的方法
protected fun animatorEnd() {}
//选中--执行的方法
protected fun unChecked() {}
//未选中--执行的方法
protected fun checked() {
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BaseSwitch">
<!--off属性-->
<attr name="track_color_off" format="color" />
<attr name="thumb_color_off" format="color" />
<attr name="stroke_color_off" format="color" />
<attr name="text_color_off" format="color" />
<attr name="text_size_off" format="dimension" />
<attr name="text_off" format="string" />
<!--on属性-->
<attr name="track_color_on" format="color" />
<attr name="thumb_color_on" format="color" />
<attr name="stroke_color_on" format="color" />
<attr name="text_color_on" format="color" />
<attr name="text_size_on" format="dimension" />
<attr name="text_on" format="string" />
<!--其它属性-->
<attr name="checked" format="boolean" />
<attr name="text_show" format="boolean" />
<attr name="animator_duration" format="integer" />
<attr name="stroke_width" format="dimension" />
</declare-styleable>
<declare-styleable name="LSwitch">
<attr name="track_radius" format="dimension" />
<attr name="track_height" format="dimension" />
<attr name="thumb_radius" format="dimension" />
<attr name="thumb_height" format="dimension" />
<attr name="thumb_width" format="dimension" />
</declare-styleable>
<declare-styleable name="KSwitch">
<!--按钮样式对应UI规范中的主要按钮,次要按钮-->
<attr name="switchType" format="enum">
<enum name="main" value="0" />
<enum name="sub" value="1" />
<enum name="text" value="2" />
</attr>
</declare-styleable>
</resources>