Android 中的 SeekBar(拖动条)是 ProgressBar 的可交互版本,用户可以通过拖动 thumb(滑块/拇指)来调节进度值。系统自带的 SeekBar 样式比较单一,在实际产品中几乎都需要自定义(颜色、圆角、渐变、thumb 形状、进度文字、禁用状态等)。
下面从 2025–2026 年实际开发角度,给你一套最实用的自定义 SeekBar 方案,按复杂度递增排列。
1. 最常用方式:通过 XML + layer-list / clip drawable 自定义(推荐 80% 场景)
优点:无需写 Java/Kotlin 代码,兼容性好,性能最高
缺点:不能动态改变 thumb 内容(如文字、图片随进度变)
步骤
- res/drawable/seekbar_bg.xml (背景轨道 – 灰色底)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#E0E0E0" /> <!-- 未激活部分颜色 -->
<corners android:radius="8dp" /> <!-- 圆角 -->
<size android:height="8dp" /> <!-- 轨道高度 -->
</shape>
- res/drawable/seekbar_progress.xml (已走过的进度 – 渐变/纯色)
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="#E0E0E0" />
<corners android:radius="8dp" />
<size android:height="8dp" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape android:shape="rectangle">
<gradient
android:startColor="#FF4081"
android:endColor="#3F51B5"
android:angle="0" /> <!-- 渐变色 -->
<corners android:radius="8dp" />
<size android:height="8dp" />
</shape>
</clip>
</item>
</layer-list>
- res/drawable/seekbar_thumb.xml (滑块)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="#FF4081" />
<size android:width="28dp" android:height="28dp" />
<stroke android:width="4dp" android:color="#33FF4081" /> <!-- 按下光环 -->
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="#FF4081" />
<size android:width="24dp" android:height="24dp" />
<stroke android:width="3dp" android:color="#FFFFFF" />
</shape>
</item>
</selector>
- 布局中使用
<SeekBar
android:id="@+id/custom_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="30"
android:progressDrawable="@drawable/seekbar_progress"
android:thumb="@drawable/seekbar_thumb"
android:thumbOffset="0dp" <!-- 重要:让 thumb 居中对齐轨道 -->
android:minHeight="30dp" <!-- 增大触摸热区 -->
android:maxHeight="30dp" />
小技巧:
android:thumbOffset="0dp"→ 让 thumb 中心对齐轨道中心(默认有偏移)- 想让轨道更粗 → 同时设置
minHeight和maxHeight相同值 - 想禁用时变灰 → 用
android:enabled="false"+ selector 区分状态
2. 进阶:Thumb 上显示当前进度文字(最常见需求)
方案一:自定义 SeekBar 类 + 在 onDraw 画文字(推荐)
class TextOnThumbSeekBar @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : androidx.appcompat.widget.AppCompatSeekBar(context, attrs, defStyleAttr) {
private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.WHITE
textSize = 14f.spToPx(context)
textAlign = Paint.Align.CENTER
}
private val bgPaint = Paint().apply {
color = Color.parseColor("#33000000")
style = Paint.Style.FILL
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 计算 thumb 中心位置
val thumb = thumb ?: return
val thumbBounds = thumb.bounds
val thumbX = (thumbBounds.left + thumbBounds.right) / 2f + paddingLeft
val thumbY = height / 2f
val progressText = progress.toString()
// 画圆形背景(可选)
canvas.drawCircle(thumbX, thumbY, 20f, bgPaint)
// 画文字
canvas.drawText(progressText, thumbX, thumbY - (textPaint.fontMetrics.ascent + textPaint.fontMetrics.descent) / 2, textPaint)
}
}
<!-- 布局中使用自定义类 -->
<你的包名.TextOnThumbSeekBar
android:id="@+id/seekbar_with_text"
... />
方案二:用 View作为 thumb(更灵活,但性能稍差)
fun getThumb(progress: Int): Drawable {
val tv = TextView(context).apply {
text = progress.toString()
setTextColor(Color.WHITE)
setBackgroundResource(R.drawable.round_bg_purple)
gravity = Gravity.CENTER
setPadding(12.dp, 6.dp, 12.dp, 6.dp)
measure(0, 0)
layout(0, 0, measuredWidth, measuredHeight)
}
return BitmapDrawable(resources, tv.drawToBitmap())
}
// 在代码中设置
seekBar.thumb = getThumb(seekBar.progress)
3. 更高级玩法(2025–2026 常见需求)
| 需求 | 实现方式简述 | 推荐优先级 |
|---|---|---|
| 渐变进度条 | layer-list + gradient | ★★★★★ |
| Thumb 带阴影/发光 | shape + elevation / layer-list 多层 | ★★★★☆ |
| 垂直 SeekBar | 自定义 View 或 rotation 270°(注意触摸) | ★★★☆☆ |
| 离散点(步进) | android:thumbTint + setKeyProgressIncrement() | ★★★★☆ |
| 带刻度 + 文字指示 | 继承 SeekBar + onDraw 画刻度线 | ★★★★☆ |
| 视频进度条(缩略图) | 自定义 thumb + BitmapDrawable 动态更新 | ★★★☆☆ |
| 禁用/只读状态美化 | selector + state_enabled | ★★★★★ |
| 触摸热区更大 | minHeight/maxHeight 设大值 | ★★★★★ |
4. 快速 Checklist(生产常用属性)
android:progressTint="#FF4081" <!-- API21+ 进度颜色 -->
android:thumbTint="#FF4081" <!-- 拇指颜色 -->
android:thumbTintMode="src_in" <!-- 着色模式 -->
android:progressBackgroundTint="#E0E0E0" <!-- 背景颜色 -->
android:splitTrack="false" <!-- 不要分割轨道(常见需求) -->
5. 常见问题 & 解决方案(2025 现状)
- Thumb 不居中 →
thumbOffset="0dp"+ 确保 thumb drawable 宽高一致 - 触摸区域太小 →
minHeight和maxHeight设为 40–60dp - 进度条不圆角 → 必须在 shape / layer-list 里都设置
corners - API < 21 渐变无效 → 用 layer-list + scale 模拟
- 想完全自定义(不继承 SeekBar) → 推荐用 Slider(Material 3)或 RangeSlider,但 SeekBar 兼容性仍最强
需要哪种风格的完整代码示例?
- 纯 XML 渐变圆角(最简单)
- Thumb 带数字(最常用)
- 垂直 SeekBar
- 带刻度线的音量条
- Material You 风格动态颜色
告诉我需求,我直接给你可复制的完整代码!