Android自定义水平进度条实现求助:无法复刻目标样式
Android 实现指定样式的自定义进度条
从你提供的样式图来看,这是一款两端圆角、纯色背景+纯色填充的横向进度条,下面提供两种实现方案,可根据需求选择:
方案一:XML Drawable 实现(简单快捷)
这种方式无需自定义View,仅通过Drawable文件即可实现,适合静态样式需求。
1. 创建背景Drawable(res/drawable/bg_progress_bar.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="16dp" /> <!-- 可选:添加边框,不需要可删除 --> <stroke android:width="1dp" android:color="#D0D0D0" /> </shape>
2. 创建组合进度条Drawable(res/drawable/progress_bar_combined.xml)
用scale标签保证进度不满时右侧仍为圆角:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 背景层 --> <item android:drawable="@drawable/bg_progress_bar" /> <!-- 进度填充层 --> <item android:id="@android:id/progress"> <scale android:scaleWidth="100%" android:scaleGravity="left"> <shape android:shape="rectangle"> <!-- 进度填充色,替换为你需要的蓝色 --> <solid android:color="#42A5F5" /> <!-- 与背景一致的圆角半径 --> <corners android:radius="16dp" /> </shape> </scale> </item> </layer-list>
3. 在布局中使用ProgressBar
<ProgressBar android:id="@+id/customProgressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="16dp" android:layout_margin="16dp" android:progressDrawable="@drawable/progress_bar_combined" android:progress="60" />
方案二:自定义View实现(灵活可控)
如果需要动态调整颜色、圆角、进度动画等复杂需求,建议使用自定义View:
1. 自定义View代码(Kotlin)
import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.graphics.RectF import android.util.AttributeSet import android.view.View import androidx.core.content.ContextCompat class RoundedProgressBar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { private var progress = 0f private var maxProgress = 100f private var bgColor = ContextCompat.getColor(context, android.R.color.darker_gray) private var progressColor = ContextCompat.getColor(context, android.R.color.holo_blue_light) private var cornerRadius = 16f private var barHeight = 16f private val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = bgColor style = Paint.Style.FILL } private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = progressColor style = Paint.Style.FILL } private val bgRect = RectF() private val progressRect = RectF() init { attrs?.let { val typedArray = context.obtainStyledAttributes(it, R.styleable.RoundedProgressBar) progress = typedArray.getFloat(R.styleable.RoundedProgressBar_progress, 0f) maxProgress = typedArray.getFloat(R.styleable.RoundedProgressBar_maxProgress, 100f) bgColor = typedArray.getColor(R.styleable.RoundedProgressBar_bgColor, bgColor) progressColor = typedArray.getColor(R.styleable.RoundedProgressBar_progressColor, progressColor) cornerRadius = typedArray.getDimension(R.styleable.RoundedProgressBar_cornerRadius, cornerRadius) barHeight = typedArray.getDimension(R.styleable.RoundedProgressBar_barHeight, barHeight) typedArray.recycle() updatePaints() } } private fun updatePaints() { bgPaint.color = bgColor progressPaint.color = progressColor } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val desiredHeight = barHeight.toInt() + paddingTop + paddingBottom val measuredHeight = resolveSize(desiredHeight, heightMeasureSpec) setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), measuredHeight) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) val left = paddingLeft.toFloat() val right = width - paddingRight.toFloat() val top = paddingTop + (height - paddingTop - paddingBottom - barHeight) / 2 val bottom = top + barHeight // 绘制背景圆角矩形 bgRect.set(left, top, right, bottom) canvas.drawRoundRect(bgRect, cornerRadius, cornerRadius, bgPaint) // 绘制进度圆角矩形 val progressWidth = (right - left) * (progress / maxProgress) progressRect.set(left, top, left + progressWidth, bottom) canvas.drawRoundRect(progressRect, cornerRadius, cornerRadius, progressPaint) } // 对外提供设置进度的方法 fun setProgress(progress: Float) { this.progress = progress.coerceIn(0f, maxProgress) invalidate() } // 对外提供设置最大进度的方法 fun setMaxProgress(max: Float) { maxProgress = max invalidate() } }
2. 添加自定义属性(res/values/attrs.xml)
<resources> <declare-styleable name="RoundedProgressBar"> <attr name="progress" format="float" /> <attr name="maxProgress" format="float" /> <attr name="bgColor" format="color" /> <attr name="progressColor" format="color" /> <attr name="cornerRadius" format="dimension" /> <attr name="barHeight" format="dimension" /> </declare-styleable> </resources>
3. 在布局中使用自定义View
<com.yourpackage.RoundedProgressBar android:id="@+id/customRoundedProgress" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp" app:bgColor="#E0E0E0" app:cornerRadius="16dp" app:barHeight="16dp" app:progressColor="#42A5F5" app:maxProgress="100" app:progress="60" />
额外优化建议
- 若需要渐变进度条,可将Drawable中的
solid标签替换为gradient标签,示例:
<gradient android:startColor="#42A5F5" android:endColor="#1E88E5" android:angle="0" />
- 圆角半径建议设置为进度条高度的一半,这样两端会呈现半圆效果,与样式图更匹配。
内容的提问来源于stack exchange,提问作者Faizan Ahmad
相关产品推荐
相关产品推荐

