You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:45:47