Android SeekBar 垂直滚动条实现——Kotlin

本文介绍了一种自定义的myVerticalSeekBar控件,通过继承AppCompatSeekBar并重写关键方法,实现了垂直方向的SeekBar。代码中详细展示了如何设置拇指、监听滑动事件以及调整滑块位置。适用于需要垂直布局的进度条应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工程目录

 

垂直SeekBar实现代码

package com.okk.vcontroller

import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MotionEvent


class myVerticalSeekBar : androidx.appcompat.widget.AppCompatSeekBar{
    private var mThumb: Drawable? = null
    private var mOnSeekBarChangeListener: OnSeekBarChangeListener? = null

    constructor(context: Context):super(context)
    constructor(context: Context, attrs: AttributeSet):super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, style: Int):super(context, attrs, style)

    override fun setOnSeekBarChangeListener(l: OnSeekBarChangeListener?) {
        mOnSeekBarChangeListener = l
    }

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

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec)
        setMeasuredDimension(measuredHeight, measuredWidth)
    }

    override fun onDraw(c: Canvas) {
        c.rotate(-90f)
        c.translate(-height.toFloat(), 0f)
        super.onDraw(c)
    }

    fun onProgressRefresh(scale: Float, fromUser: Boolean) {
        val thumb = mThumb
        if (thumb != null) {
            setThumbPos(height, thumb, scale, Int.MIN_VALUE)
            invalidate()
        }
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener!!.onProgressChanged(this, progress, fromUser)
        }
    }

    private fun setThumbPos(w: Int, thumb: Drawable, scale: Float, gap: Int) {
        val available = w - paddingLeft - paddingRight
        val thumbWidth = thumb.intrinsicWidth
        val thumbHeight = thumb.intrinsicHeight
        val thumbPos = (scale * available + 0.5f).toInt()

        // int topBound = getWidth() / 2 - thumbHeight / 2 - getPaddingTop();
        // int bottomBound = getWidth() / 2 + thumbHeight / 2 - getPaddingTop();
        val topBound: Int
        val bottomBound: Int
        if (gap == Int.MIN_VALUE) {
            val oldBounds: Rect = thumb.bounds
            topBound = oldBounds.top
            bottomBound = oldBounds.bottom
        } else {
            topBound = gap
            bottomBound = gap + thumbHeight
        }
        thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound)
    }

    override fun setThumb(thumb: Drawable?) {
        mThumb = thumb
        super.setThumb(thumb)
    }

//    fun onStartTrackingTouch() {
//        if (mOnSeekBarChangeListener != null) {
//            mOnSeekBarChangeListener!!.onStartTrackingTouch(this)
//        }
//    }
//
//    fun onStopTrackingTouch() {
//        if (mOnSeekBarChangeListener != null) {
//            mOnSeekBarChangeListener!!.onStopTrackingTouch(this)
//        }
//    }
//
//    private fun attemptClaimDrag() {
//        if (parent != null) {
//            parent.requestDisallowInterceptTouchEvent(true)
//        }
//    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!isEnabled) {
            return false
        }
//        when (event.action) {
//            MotionEvent.ACTION_DOWN -> {
//                isPressed = true
//                onStartTrackingTouch()
//            }
//            MotionEvent.ACTION_MOVE -> {
//                attemptClaimDrag()
//                progress = max - (max * event.y / height).toInt()
//            }
//            MotionEvent.ACTION_UP -> {
//                onStopTrackingTouch()
//                isPressed = false
//            }
//            MotionEvent.ACTION_CANCEL -> {
//                onStopTrackingTouch()
//                isPressed = false
//            }
//        }
        when (event.action) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_UP -> {
                //progress =  max - (max * event.y / height).toInt()
                //将浮点数 强制类型转换为整数  是只取整数部分
                //正数+0.5,负数-0.5,然后取整即可得到四舍五入
                //实现滑条拖动半拉可以选择
                progress =  max - ((max * event.y / height)+0.5).toInt()

                onSizeChanged(width, height, 0, 0)
            }
            MotionEvent.ACTION_CANCEL -> {
            }
        }
        return true
    }
}

引用方式

 

<com.okk.vcontroller.myVerticalSeekBar
                android:id="@+id/sb_speed"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:max="20"
                android:thumb="@drawable/vertical_seek_bar_style"
                />
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

指针不南

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

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

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

打赏作者

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

抵扣说明:

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

余额充值