如何为环形滑动条(Circle SeekBar)填充当前值区域颜色?
环形滑动条(Circle SeekBar)当前值区域填充颜色实现方案
自定义View实现(推荐)
通过重写View的onDraw方法手动绘制背景环形和进度填充区域,同时支持触摸拖动调整进度,完全可控且无需依赖第三方库。
1. 定义自定义属性
在res/values/attrs.xml中添加配置属性,方便在布局中直接调整样式:
<declare-styleable name="CircleSeekBar"> <attr name="progressColor" format="color" /> <attr name="backgroundColor" format="color" /> <attr name="maxProgress" format="integer" /> <attr name="currentProgress" format="integer" /> <attr name="circleWidth" format="dimension" /> </declare-styleable>
2. 编写自定义CircleSeekBar类
class CircleSeekBar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { private var progressColor: Int = Color.BLUE private var backgroundColor: Int = Color.GRAY private var maxProgress: Int = 100 private var currentProgress: Int = 50 private var circleWidth: Float = 20f private val paint = Paint(Paint.ANTI_ALIAS_FLAG) private val rectF = RectF() init { val typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleSeekBar) progressColor = typedArray.getColor(R.styleable.CircleSeekBar_progressColor, progressColor) backgroundColor = typedArray.getColor(R.styleable.CircleSeekBar_backgroundColor, backgroundColor) maxProgress = typedArray.getInt(R.styleable.CircleSeekBar_maxProgress, maxProgress) currentProgress = typedArray.getInt(R.styleable.CircleSeekBar_currentProgress, currentProgress) circleWidth = typedArray.getDimension(R.styleable.CircleSeekBar_circleWidth, circleWidth) typedArray.recycle() } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)) setMeasuredDimension(size, size) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val centerX = width / 2f val centerY = height / 2f val radius = Math.min(centerX, centerY) - circleWidth / 2 // 绘制背景环形 paint.color = backgroundColor paint.style = Paint.Style.STROKE paint.strokeWidth = circleWidth canvas.drawCircle(centerX, centerY, radius, paint) // 绘制进度填充环形 paint.color = progressColor paint.style = Paint.Style.STROKE paint.strokeCap = Paint.Cap.ROUND // 可选:设置进度端点为圆角 val sweepAngle = (currentProgress.toFloat() / maxProgress) * 360f rectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius) canvas.drawArc(rectF, -90f, sweepAngle, false, paint) } // 对外暴露设置进度的方法 fun setCurrentProgress(progress: Int) { currentProgress = progress.coerceIn(0, maxProgress) invalidate() } // 处理触摸拖动,实现交互式调整进度 override fun onTouchEvent(event: MotionEvent): Boolean { when (event.action) { MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> { val centerX = width / 2f val centerY = height / 2f val dx = event.x - centerX val dy = event.y - centerY var angle = Math.toDegrees(Math.atan2(dy.toDouble(), dx.toDouble())).toFloat() if (angle < -90) angle += 360 angle += 90 // 将起始角度调整为环形顶部 val progress = ((angle / 360f) * maxProgress).toInt() setCurrentProgress(progress) return true } } return super.onTouchEvent(event) } }
3. 在布局中使用
<com.yourpackage.CircleSeekBar android:layout_width="200dp" android:layout_height="200dp" app:progressColor="@color/blue" app:backgroundColor="@color/light_gray" app:maxProgress="100" app:currentProgress="50" app:circleWidth="20dp" />
核心逻辑说明
- 通过
canvas.drawArc绘制对应进度的弧形区域,sweepAngle由当前进度与最大进度的比例计算得出,精准匹配当前值区域。 - 触摸事件中通过计算触摸点与中心的夹角,转换为对应的进度值,实现拖动交互。
内容的提问来源于stack exchange,提问作者JAEYUN
相关产品推荐
相关产品推荐

