自定义渐变-圆角ProgressBar

先上进度条样式:

image.png

再上效果:

a939381496fdfec9824dce9612718455.gif

在平时开发中,常常遇到一些特殊需求,就比方我今天写的这篇。
UI设计让我必须搞一个圆角的进度条,虽然不是特别难,但本着方便你我,下次使用拿来主义,我今天花几分钟自定义一个。

说来也巧,在正常的开发时,发现只能对进度条的背景色设置圆角,进度条却始终是方的,令我百思不得姐~~

正式代码我放到最后

没错,我不想写了,这就是最后~~~~

实现最终代码

step1.自定义一个Progressbar
/**
 * Created by gudd on 2024/9/27.
 * 自定义该view,主要就是为了实现将进度条设置为圆角
 */
public class RoundedCornerProgressBar extends ProgressBar {
    private final Paint paint;
    private final RectF rectF;
    // 这两个颜色主要用来从resource中获取颜色,不至于将色值写死在自定义view中。
    private int progressColorStart = 0;
    private int progressColorEnd = 0;

    public CustomProgressBar(Context context) {
        this(context, null);
    }

    public CustomProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        paint = new Paint();
        rectF = new RectF();
        progressColorStart = ContextCompat.getColor(context, R.color.colorStart);
        progressColorEnd = ContextCompat.getColor(context, R.color.colorEnd);
        paint.setAntiAlias(true);
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        super.draw(canvas);

        float radius = 40f;
        float width = getWidth();
        float height = getHeight();


        // 设置圆角矩形区域
        rectF.set(0f, 0f, width * getProgress() / getMax(), height);
        // 设置渐变色,两种方法,喜欢哪种用哪种。
        /*paint.setShader(new LinearGradient(0f, 0f, width, 0f,
            progressColorStart, progressColorEnd, Shader.TileMode.CLAMP));*/
        paint.setShader(new LinearGradient(0f, 0f, width, 0f,
                Color.parseColor("#FF5722"), Color.parseColor("#FFC107"), Shader.TileMode.CLAMP));

        canvas.drawRoundRect(rectF, radius, radius, paint); // 绘制圆角矩形
    }

    // 设置连续动画,从左往右类似加载
    public void setProgressWithAnimation(int progress, long duration) {
        ObjectAnimator animator = ObjectAnimator.ofInt(this, "progress", this.getProgress(), progress);
        animator.setDuration(duration);
        animator.start();
    }
}
step2.创建一个drawable,用来设置progressbar的背景,其实也可以写到自定义view中,但我这里为了方便就写在xml里了,因为这个比较简单,不像圆角进度条一样圆角显示异常。

创建一个drawable文件叫:custom_drawable.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>
            <corners android:radius="20dp" />
            <solid android:color="#e0e0e0" />
        </shape>
    </item>
    <!-- 下面这边注释主要是因为这段虽然可以设置进度条渐变色,但并不能显示圆角,这让我不得不把它写在注释里面-->
    <!--<item android:id="@android:id/progress">
        <clip>
            <shape >
                <corners android:radius="20dp" /> &lt;!&ndash; 圆角 &ndash;&gt;
                <gradient
                    android:startColor="#FF5722"
                    android:endColor="#FFC107"
                    android:angle="0"/> &lt;!&ndash; 渐变色 &ndash;&gt;
            </shape>
        </clip>
    </item>-->
</layer-list>
step3.在自己的布局中添加这个自定义view,并设置drawable背影
<com.gudd.importmodulepreview.CustomProgressBar
        android:id="@+id/customProgressBar"
        android:layout_width="0dp"
        android:layout_height="20dp"
        android:layout_margin="16dp"
        android:max="100"
        android:progress="0"
        android:progressDrawable="@drawable/custom_progress"   // 这一行就是我设置的背景
        style="?android:attr/progressBarStyleHorizontal"       // 这一行需要小心,不设置则有可能不是横向进度条样式
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:indeterminate="false"/>                         //这个确保 indeterminate="false",否则进度条将会显示为转圈样式
step4.在MainActivity.java中设置进度。可以有动画效果
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        CustomProgressBar progressBar = findViewById(R.id.customProgressBar);

        progressBar.postDelayed(()->{
            progressBar.setProgressWithAnimation(80, 1000); // 设置动画时长为 1 秒,进度为 80
        },2000);
    }
}

接上部分继续优化

优化需求

根据上面已经实现的部分,如今又来一个新界面,该界面的圆角又不是需要那么圆了,需要带点方的圆角,具体描述说也说不清楚,上个图吧,就像下面这图一样,不要太圆的圆角:


image.png

所以目前为了实现该功能总不能再写一个类对吧,这里修改下代码,让它变为动态设置,写在xml上,如果谁需要写个方法告诉我,我加上,这次不加是因为我比较懒!!!
对了,这次把动态设置背景的也给加上。
注意:该类设置了动态背景后,将不能使用(提前说明)

// 设置该属性将无效
android:progressDrawable="@drawable/custom_progress_drawable"了。

首先需要加一个“declare-styleable”

step1:在资源目录的res/values/attrs中增加代码,没有attrs需要创建一个
<declare-styleable name="RoundedCornerProgressBar">
        <attr name="progressBarBackground" format="reference|color" />
        <attr name="progressColorStart" format="reference|color" />
        <attr name="progressColorEnd" format="reference|color" />
        <attr name="progressRadius" format="dimension" />
</declare-styleable>
step2:修改自定义View
/**
 * Created by gudd on 2024/9/27.
 * 该自定义view在使用中将使{android:progressDrawable="@drawable/custom_progress"}设置无效。
 * 注:设置背景请使用app:progressBarBackground="#FFFFFF"或app:progressBarBackground="@color/red"
 */
public class RoundedCornerProgressBar extends ProgressBar {
    private final Paint paint;
    private final Paint paintBg;    // 增加
    private final RectF rectF;
    private final RectF rectFBg;    // 增加
    private final int progressBarBackground;    // 增加
    private final int progressColorStart;    // 增加
    private final int progressColorEnd;    // 增加
    private final float progressRadius;    // 增加

    public RoundedCornerProgressBar(Context context) {
        this(context, null);
    }

    public RoundedCornerProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundedCornerProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        setProgressDrawable(null); // 增加  去除默认背景
        paint = new Paint();
        paintBg = new Paint();    // 增加
        rectF = new RectF();
        rectFBg = new RectF();    // 增加
        paint.setAntiAlias(true);

        // 增加,这部分使用try-with-resources语句,执行到末尾自动关闭typedArray,
        // 如果报错,请使用:try{}finally{}语句
        try (TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornerProgressBar)) {
            progressBarBackground = typedArray.getColor(R.styleable.RoundedCornerProgressBar_progressBarBackground, Color.GRAY);
            progressColorStart = typedArray.getColor(R.styleable.RoundedCornerProgressBar_progressColorStart, Color.parseColor("#FFC107"));
            progressColorEnd = typedArray.getColor(R.styleable.RoundedCornerProgressBar_progressColorEnd, Color.parseColor("#FF5722"));
            progressRadius = typedArray.getDimension(R.styleable.RoundedCornerProgressBar_progressRadius, 16.f);
        }

    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        super.draw(canvas);

        float radius = progressRadius;     // 修改这行
        float width = getWidth();
        float height = getHeight();

        // 增加 绘制背景
        paintBg.setColor(progressBarBackground);
        rectFBg.set(0f, 0f, width, height);
        canvas.drawRoundRect(rectFBg, radius, radius, paintBg); // 绘制圆角背景

        // 设置圆角矩形区域
        rectF.set(0f, 0f, width * getProgress() / getMax(), height);
        // 设置渐变色
        paint.setShader(new LinearGradient(0f, 0f, width, 0f,
                progressColorStart, progressColorEnd, Shader.TileMode.CLAMP));
        canvas.drawRoundRect(rectF, radius, radius, paint); // 绘制圆角矩形
    }

    public void setProgressWithAnimation(int progress, long duration) {
        ObjectAnimator animator = ObjectAnimator.ofInt(this, "progress", this.getProgress(), progress);
        animator.setDuration(duration);
        animator.start();
    }
}
step3:在布局中使用
<com.gudd.importmodulepreview.RoundedCornerProgressBar
        android:id="@+id/customProgressBar"
        android:layout_width="0dp"
        android:layout_height="20dp"
        android:layout_margin="16dp"
        android:max="100"
        android:progress="0"
        android:progressDrawable="@drawable/custom_progress"  // 该行设置将无效,请删除该行
        style="?android:attr/progressBarStyleHorizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:indeterminate="false"
        app:progressColorStart="#FFC107"   // 进度条起点色
        app:progressColorEnd="#FF5722"    // 进度条终点色
        app:progressBarBackground="#e2e2e2"  // 进度条背景色
        app:progressRadius="20dp"/>      // 进度条背景和前景的圆角度数

完!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容