Switch自定义视图

在这里插入图片描述

 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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄毛火烧雪下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值