Kotlin-->范围选择进度条, 双向SeekBar

这里写图片描述

首先了解下, 自定义View的三部曲.

1:onMeasure方法

此方法主要目的, 就是根据xml的
android:layout_width="wrap_content"
android:layout_height="wrap_content"

wrap_content match_parent 这2个属性, 来确定测量自身的大小.
当然, 这2个值, 只是parent告诉你, 需要按照此规则来测量, 如果你是一个坏孩子, 那么可以无视测量规则, 任意设置一个宽度和高度, 比如: setMeasuredDimension(1万, 2万) 就是如此简单;

2:onLayout方法

如果你是自定义View, 此方法可以不必override
如果你是自定义的ViewGroup, 那么就必须override, 此方法的目的就是由你决定child view在界面上的位置.

3:onDraw方法

在这个方法里面, 你可以展开你天才般的做图功能, 想画啥就画啥. 美美的view, 就这样出来了.
友情提示:如果你是自定义的ViewGroup, 还需要调用setWillNotDraw(false)方法, 否则onDraw方法不会执行哦


不着急, 分析一波:

1: 有2个可以滑动的浮子
2: 需要一个轨道, 浮子在轨道上滑动
3: 浮子之间的颜色不一样
4: 浮子上面有进度文本

步骤不多, 还是很简单就能实现的.

因为都是一个draw操作, 所以这里就直接贴上onDraw的代码了:

onDraw

override fun onDraw(canvas: Canvas) {
   //canvas.drawColor(Color.parseColor("#80000000"))

     paint.style = Paint.Style.FILL
     paint.color = trackColor
     paint.textSize = textSize

     //绘制轨道
     trackRectF.set((paddingLeft + thumbRadius).toFloat(), trackTop,
             measuredWidth.toFloat() - paddingRight - thumbRadius, trackTop + trackHeight)
     canvas.drawRoundRect(trackRectF, trackRoundRadius.toFloat(), trackRoundRadius.toFloat(), paint)

     //计算浮子矩形坐标位置
     calcThumbValueRect()

     //绘制进度
     paint.style = Paint.Style.FILL
     paint.color = progressColor
     progressRectF.set(minValueRectF.centerX(), trackRectF.top, maxValueRectF.centerX(), trackRectF.bottom)
     canvas.drawRoundRect(progressRectF, trackRoundRadius.toFloat(), trackRoundRadius.toFloat(), paint)

     //绘制浮子
     drawThumb(canvas, minValueRectF)
     drawThumb(canvas, maxValueRectF)

     //绘制提示文本
     drawText(canvas, minValueRectF, currentMinValue)
     drawText(canvas, maxValueRectF, currentMaxValue)
 }

 private fun drawThumb(canvas: Canvas, rectF: RectF) {
     paint.style = Paint.Style.FILL
     paint.color = thumbColor
     canvas.drawCircle(rectF.centerX(), rectF.centerY(), thumbRadius.toFloat(), paint)

     //绘制浮子外圈
     paint.style = Paint.Style.STROKE
     paint.strokeWidth = 2 * density
     paint.color = thumbOutLineColor
     canvas.drawCircle(rectF.centerX(), rectF.centerY(), thumbRadius.toFloat() - 1 * density, paint)
 }

 private fun drawText(canvas: Canvas, rectF: RectF, progress: Int) {
     paint.style = Paint.Style.FILL_AND_STROKE
     paint.color = textColor
     paint.strokeWidth = 1f

     val text: String = rangeListener?.getProgressText(progress) ?: "$progress%"
     canvas.drawText(text,
             Math.min(Math.max(0f, rectF.centerX() - textWidth(paint, text) / 2),
                     viewWidth - textWidth(paint, text)),
             paddingTop + textHeight(paint) - paint.descent(),
             paint)
 }

 private fun calcThumbValueRect() {
     val x = (viewWidth - 2 * thumbRadius) * (currentMinValue.toFloat() / 100f) + paddingLeft
     minValueRectF.set(
             x,
             trackTop + trackHeight / 2 - thumbRadius,
             x + 2 * thumbRadius,
             trackTop + trackHeight / 2 + thumbRadius
     )

     val x2 = (viewWidth - 2 * thumbRadius) * (currentMaxValue.toFloat() / 100f) + paddingLeft
     maxValueRectF.set(
             x2,
             trackTop + trackHeight / 2 - thumbRadius,
             x2 + 2 * thumbRadius,
             trackTop + trackHeight / 2 + thumbRadius
     )
 }

手势处理:

/**手势按在那个点上, 不分最大点和最小点*/
    private var touchValue: Int = -1
    private var notTouchValue: Int = -1

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val action = MotionEventCompat.getActionMasked(event)
        when (action) {
            MotionEvent.ACTION_DOWN -> {
                if (minValueRectF.contains(event.x, event.y)) {
                    touchValue = currentMinValue
                    notTouchValue = currentMaxValue
                } else if (maxValueRectF.contains(event.x, event.y)) {
                    touchValue = currentMaxValue
                    notTouchValue = currentMinValue
                } else {
                    touchValue = -1
                    notTouchValue = -1
                }
            }
            MotionEvent.ACTION_MOVE -> {
                if (touchValue >= 0) {
                    parent.requestDisallowInterceptTouchEvent(true)

                    //按在了点上
                    touchValue = ((event.x - paddingLeft - thumbRadius) / (viewWidth - 2 * thumbRadius) * 100).toInt()
                    touchValue = ensureValue(touchValue)
                    //L.e("call: onTouchEvent ->$viewWidth ${event.x}  $touchValue")

                    if (Math.abs(touchValue - notTouchValue) >= MIN_RANGE) {
                        currentMinValue = Math.min(touchValue, notTouchValue)
                        currentMaxValue = Math.max(touchValue, notTouchValue)

                        postInvalidate()

                        rangeListener?.onRangeChange(currentMinValue, currentMaxValue)
                    }

                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                parent.requestDisallowInterceptTouchEvent(false)
            }
        }
        return true
    }

联系作者

请使用QQ扫码加群, 小伙伴们在等着你哦!

关注我的公众号, 每天都能一起玩耍哦!

猜你喜欢

转载自blog.csdn.net/angcyo/article/details/78027824
今日推荐