html 滑动条 双向滑动,双向水平滑动条

class DoubleSeekBarView :View {

constructor(ctx:Context) :this(

ctx, ContextCompat.getDrawable(ctx, R.drawable.seek_bar_thumb)!!.toBitmap(), { _, _,         _ -> }

)

constructor(ctx:Context, attrs:AttributeSet?) :super(ctx, attrs, 0) {

this.sliderBitmap= ContextCompat.getDrawable(ctx,                 R.drawable.seek_bar_thumb)!!.toBitmap()

this.onSliderListener= { _, _, _ -> }

}

constructor(

ctx:Context,

sliderBitmap:Bitmap,

onSliderListener:(slidingDir:Int, currentLeft:Float, currentRight:Float) -> Unit = { _, _, _         -> }

) :super(ctx) {

this.sliderBitmap= sliderBitmap

this.onSliderListener= onSliderListener

}

companion object {

const val LEFT= 1

const val RIGHT= 2

}

var onSliderListener:(slidingDir:Int, currentLeft:Float, currentRight:Float) -> Unit

var currentLeft= 0f

var currentRight= 1f

private var lineWidth= 0 // 能滑动的宽度,即线宽

var lineHeight= dip(5)

private var slidingDir= LEFT // 滑动方向

private var sliderWidth= 0 // 滑块宽度,即 sliderBitmap 宽度

set(value) {

field= value

srcRect.right= field

}

private var sliderHeight= 0 // 滑块高度,即 sliderBitmap 高度

set(value) {

field= value

srcRect.bottom= field

}

private var sliderBitmap:Bitmap

set(value) {

field= value

sliderWidth= field.width

sliderHeight= field.height

}

private val paint by lazy { Paint() }

private fun getSliderPaint():Paint {

paint.reset()

paint.isAntiAlias = true

return paint

}

private fun getLinePaint(colorRes:Int):Paint {

paint.reset()

paint.style = Paint.Style.FILL

paint.color = ContextCompat.getColor(context, colorRes)

paint.isAntiAlias = true

return paint

}

private var srcRect= Rect(0, 0, 0, 0)

private var leftDst= RectF(0f, 0f, 0f, 0f)

private var rightDst= RectF(0f, 0f, 0f, 0f)

/** * 左滑块位置矩形 */

private fun getLeftDst():RectF {

leftDst.set(

currentLeft* lineWidth, (height - srcRect.height()) / 2f,

currentLeft* lineWidth+ srcRect.width(), (height + srcRect.height()) / 2f

)

return leftDst

}

/** * 右滑块位置矩形 */

private fun getRightDst():RectF {

rightDst.set(

currentRight* lineWidth, (height - srcRect.height()) / 2f,

currentRight* lineWidth+ srcRect.width(), (height + srcRect.height()) / 2f

)

return rightDst

}

private fun getLineLeft():Float {

return currentLeft* lineWidth+ sliderWidth

}

private fun getLineRight():Float {

return currentRight* lineWidth

}

override fun onSizeChanged(w:Int, h:Int, oldw:Int, oldh:Int) {

super.onSizeChanged(w, h, oldw, oldh)

lineWidth= width - sliderBitmap.width

}

override fun onDraw(canvas:Canvas?) {

// 绘制底线

canvas?.drawRect(

(width - lineWidth) / 2f, (height - lineHeight) / 2f,

(width + lineWidth) / 2f, (height + lineHeight) / 2f,

getLinePaint(R.color.whiteblue_theme_half_dark)

)

// 绘制进度线

canvas?.drawRect(

getLineLeft(), (height - lineHeight) / 2f,

getLineRight(), (height + lineHeight) / 2f,

getLinePaint(R.color.colorAccent)

)

// 绘制左滑块

canvas?.drawBitmap(sliderBitmap, srcRect, getLeftDst(), getSliderPaint())

// 绘制右滑块

canvas?.drawBitmap(sliderBitmap, srcRect, getRightDst(), getSliderPaint())

}

override fun onTouchEvent(event:MotionEvent?):Boolean {

when (event?.action) {

MotionEvent.ACTION_DOWN -> {

return checkClick(event.x, event.y)

}

MotionEvent.ACTION_MOVE -> {

val currentProgress= checkedCurrentProgress(event.x)

when (slidingDir) {

LEFT-> {

if (currentProgress>= currentRight) {

currentLeft= currentRight

invalidate()

} else {

currentLeft= currentProgress

invalidate()

}

}

RIGHT-> {

if (currentProgress<= currentLeft) {

currentRight= currentLeft

invalidate()

} else {

currentRight= currentProgress

invalidate()

}

}

}

onSliderListener(slidingDir, currentLeft, currentRight)

return true

}

}

return false

}

/**

* 经校验的当前点击的范围

* @param eventX 点击的 X 坐标

* @return 0 - 1f

*/

private fun checkedCurrentProgress(eventX:Float):Float {

val progress= (eventX - sliderBitmap.width / 2) / lineWidth

return when {

progress< 0 -> 0f

progress> 1 -> 1f

else -> progress

}

}

/**

* 检查点击是否有效,有效范围为左右滑块位置,并判断滑动方向,优先向左 (要更改

优先级把 when 里面顺序调换或另写一个函数去判断)

* @param eventX 点击的 X 坐标

* @param eventY 点击的 Y 坐标

* @return true 点击有效 else 点击无效

*/

private fun checkClick(eventX:Float, eventY:Float):Boolean {

val leftXMin= currentLeft* lineWidth

val leftXMax= currentLeft* lineWidth+ srcRect.width()

val rightXMin= currentRight* lineWidth

val rightXMax= currentRight* lineWidth+ srcRect.width()

val yMin= (height - srcRect.height()) / 2f

val yMax= (height + srcRect.height()) / 2f

return if (eventY in yMin..yMax) {

when (eventX) {

in leftXMin..leftXMax-> {

slidingDir= if (currentLeft== 0f && currentRight== 0f) RIGHTelse LEFT

true

}

in rightXMin..rightXMax-> {

slidingDir= if (currentRight== 1f && currentLeft== 1f) LEFTelse RIGHT

true

}

else -> false

}

} else false

}

/** * 最后别忘了清除 bitmap 数据引用 */

fun recycle() {

sliderBitmap.recycle()

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值