自定义实现横向圆角进度条——简易版

Android 自定义ProgressBar横向圆角 ProgressBar大家可能项目中都会用到,但是大部分都是根据UI给的符合项目主题的自定义形式的; 下面就是我们项目中一个显示学习进度的横向ProgressBar; 可以看到四个角都是圆角的,本人首先想到的是自定义,但是会发现四个角总是不能够实现,要不左侧会被切成直角,要不进度内侧会被切成直角,也是从网上查找分析,最终实现如下: 结合网上大神的示意,在此作个笔记,方便之后遇到直接拿来用,节省时间. 借鉴ProgressBar 进度条的进度两端是圆角的方法 但是根据自定义的shape 或者是 阅读详情

在这里插入图片描述
UI 说需要实现这样圆角横向进度条,好,于是我就去屁颠屁颠的 Google。下面就是我的辛酸历程。

1、 设置 ProgressBar 的 android:progressDrawable 属性

首先找到的一种实现方法就是为 ProgressBar 设置 android:progressDrawable 属性,类似于 Progress内外圆角进度条 这篇文章里面说的。

实现起来比较简单方便,但是后来在测试的时候就会发现问题,比如说在 progress 值很小的时候(max == 100 && progress == 1),进度条的显示就会出现如下情况:
在这里插入图片描述
所以,不行!不行!不行!

2、 自定义 View 来实现
2.1 模仿轮子阶段

首先,我还是去了 GayHub 去找看有没有现成的或者类似的轮子,毕竟我还是喜欢偷懒的。

在筛选了一番之后,找到一个类似的 【yongfengnice/CircleProgress】

	@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画背景
        RectF bgRectF = new RectF(0, 0, mViewWidth, mViewHeight);
        canvas.drawRoundRect(bgRectF, mViewHeight / 2, mViewHeight / 2, mBackgroundPaint);
        //画进度条
        int width = (int) (mViewWidth * (mProgress * 1.0f / mMaxProgress) + 0.5);
        if (width <= mViewHeight) {//圆形
            canvas.drawCircle(width / 2, mViewHeight / 2, width / 2, mProgressPaint);
        } else {
            RectF progressRectF = new RectF(0, 0, width, mViewHeight);
            canvas.drawRoundRect(progressRectF, mViewHeight / 2, mViewHeight / 2, mProgressPaint);
        }
    }

其实现原理,就是先用个 canvas.drawRoundRect 画背景(即图中灰色部分),然后根据进度值,如果是还没有超过圆弧的区域时,就直接画一个圆,否则就同样画一个 RoundRect。
这样,在进度值小的时候,就会感觉怪怪的,因为它右边的弧没有契合。
在这里插入图片描述

2.2 改造轮子阶段

于是乎,追求完美主义的我(实际上是混不过产品眼睛)就犯轴了,怎么才能实现下面那样更加完美的效果呢?
在这里插入图片描述

首先我想到的是,黄色进度区域用画椭圆来实现,但是苦逼的是以我现在的能力,无法算出下图标记出的两个点的 y 坐标。(当然了,赛贝尔曲线我更加 Hold 不住)
在这里插入图片描述

于是乎,我就想,我既然无法直接画出黄色进度条的部分,那么我可以再画一个跟背景一样的 RoundRect,然后去移动它,再利用 android Xfermode 去实现只显示重叠的部分(也就是进度条部分)以及原本的背景部分。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int width = (int) (mViewWidth * (mProgress * 1.0f / mMaxProgress) + 0.5f);
    //int saved = canvas.saveLayer(0,0,mViewWidth,mViewHeight, null, Canvas.ALL_SAVE_FLAG); 设定生效的区域
    //canvas.saveLayer() 有两个重载函数,如果没有指定 Layer 的区域,则默认为当前 View 的范围
    int saved = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);//开始
    onDrawPaint.setColor(colorBcg);
    //画背景
    canvas.drawRoundRect(new RectF(0, 0, mViewWidth, mViewHeight), mViewHeight / 2, mViewHeight / 2, onDrawPaint);
    onDrawPaint.setXfermode(xfermode);
    onDrawPaint.setColor(colorProgress);
    //画进度条
    canvas.drawRoundRect(new RectF(width-mViewWidth, 0, width, mViewHeight), mViewHeight / 2, mViewHeight / 2, onDrawPaint);
    onDrawPaint.setXfermode(null);
    canvas.restoreToCount(saved);//结束
}

上面就是核心代码了,主要是利用
xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP); 来实现的。

注意,画背景和进度条的逻辑需要根据 Xfermode 设置的模式结合画的顺序来弄,且需要包含在注释标注的 “开始” 与 “结束” 之间。

题外话,我开始天真的以为 Xfermode 只适用于 drawBitmap…

参考文章:


完整的源码实现

public class RoundedProgressBar extends View {

    private int mViewWidth;
    private int mViewHeight;
    private int mMaxProgress = 100;//最大进度
    private int mProgress = 0;//当前进度

    Paint onDrawPaint;
    Xfermode xfermode;

    private String colorBcg;
    private String colorProgress;

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

    public RoundedProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        setBackgroundResource(0);//移除设置的背景资源

        xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);

        onDrawPaint = new Paint();
        onDrawPaint.setFilterBitmap(false);

        colorBcg = "#1B1E33";
        colorProgress = "#FFD600";
        //需要注意的是,如果颜色设置透明度,叠加后的图也会因为设置的透明度而变化,
        //且会因 xfermode 的各种模式而受到影响,导致跟预期不同
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mViewWidth = getMeasuredWidth();
        mViewHeight = getMeasuredHeight();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = (int) (mViewWidth * (mProgress * 1.0f / mMaxProgress) + 0.5f);
//        int saved = canvas.saveLayer(0,0,mViewWidth,mViewHeight, null, Canvas.ALL_SAVE_FLAG); //设定生效的区域
        int saved = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
        onDrawPaint.setColor(Color.parseColor(colorBcg));
        canvas.drawRoundRect(new RectF(0, 0, mViewWidth, mViewHeight), mViewHeight / 2, mViewHeight / 2, onDrawPaint);
        onDrawPaint.setXfermode(xfermode);
        onDrawPaint.setColor(Color.parseColor(colorProgress));
        canvas.drawRoundRect(new RectF(width-mViewWidth, 0, width, mViewHeight), mViewHeight / 2, mViewHeight / 2, onDrawPaint);
        onDrawPaint.setXfermode(null);
        canvas.restoreToCount(saved);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mViewWidth = w;
        mViewHeight = h;
        invalidate();
    }

    /**
     * 设置当前进度
     *
     * @param progress
     */
    public void setProgress(int progress) {
        progress = progress >= 0 ? progress : 0;
        progress = progress <= mMaxProgress ? progress : mMaxProgress;
        mProgress = progress;
        invalidate();
    }

    /**
     * 设置最大进度
     *
     * @param maxProgress
     */
    public void setMaxProgress(int maxProgress) {
        mMaxProgress = maxProgress;
        invalidate();
    }
}
Android漂亮的横向和环形进度条示例 在这段XML代码中,我们指定了ProgressBar的样式为横向进度条,并将自定义样式custom_horizontal_progress应用到progressDrawable属性上。在这段XML代码中,我们指定了ProgressBar的样式为大型环形进度条,并将自定义样式custom_circular_progress应用到progressDrawable属性上。要创建一个漂亮的环形进度条,我们可以使用Android的ProgressBar组件,并为其应用自定义样式。这段代码将进度条的值设置为75。 阅读详情

相关推荐

Android 横向进度条

Android HorizontalProgressBar 横向进度条右侧有圆点

Android ProgressBar设置成横向进度条并自定义进度条颜色

将ProgressBar设置成横向进度条并修改进度条颜色

luochuanrong的博客 4682

高阶玩法——Dify生成的数据自动写入mysql数据库

采用自定义工具方式,利用 python编写一个服务sql_save_post,将接收到的内容写入指定数据库的表中,并为该服务撰写一个 OpenAPI 的 schema。配置工作流:我们以写入天气预报为例,在生成天气预报内容后,连接自定义工具“sql_save_post”,将所需的字段配置完成后,实现将生成的内容自动写入mysql数据库中。编写OpenAPI的schema:在dify平台的工具栏目,创建自定义工具,输入工具名称“sql_save_post”。工具:sql_save_post;

qq_44493378的博客 8544

Android 自定义横向进度条

private int max; private double progress; private int bgColor; private int progressColor; private int padding; private boolean openGradient; private int gradientFrom; private int gradientTo; private boolean showSecondProgres

陈志宝‑天津|Android&Java 全栈开发工程师 2725

Pseudobulk与FindMarkers单细胞差异基因分析实战对比

本文深入对比了单细胞差异基因分析中Pseudobulk与FindMarkers两种主流方法。通过实战演示,详细解析了二者在底层逻辑、数据准备、分析流程及结果解读上的核心差异,并提供了基于不同生物学问题与数据特点的选择策略,帮助研究者做出更精准的分析决策。

weixin_29218963的博客 334

SAP生产版本导入避坑大全:从‘黄灯’到‘绿灯’,详解CM_FV_MKAL_CONSISTENCY_CHECK检查函数

本文深入解析SAP生产版本导入过程中的常见问题,特别是通过`CM_FV_MKAL_CONSISTENCY_CHECK`检查函数从‘黄灯’异常到‘绿灯’正常的修复方法。涵盖静态与动态校验机制、典型异常场景诊断及批量导入最佳实践,帮助SAP运维人员高效解决生产版本管理难题。

weixin_30568591的博客 389

android自定义横向进度条,Android自定义进度条的圆角横向进度条实例详解

1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的:invalidate()方法rectf方法的应用onmeasure方法的应用2.原理画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下:3.效果图实现圆角进度条还有很多其他方法,比如在progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的。4....

weixin_35552251的博客 705

QCC51XX---人机接口设备协议( HID)

QCC51XX---人机接口设备协议( HID)

weixin_42162924的博客 820

android自定义圆角进度条,Android自定义进度条的圆角横向进度条实例详解

1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的:invalidate()方法RectF方法的应用onMeasure方法的应用2.原理画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下:3.效果图实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的。4....

weixin_30019517的博客 1257

FISCO BCOS 系列(一)—— 搭建第一个区块链网络&配置控制台指南

本文详细介绍了FISCO BCOS区块链网络的搭建与配置过程,包括环境准备、单机四节点网络搭建、控制台配置使用等核心内容。从系统要求、依赖安装开始,逐步指导如何通过脚本快速搭建区块链网络,配置控制台连接,并演示了账户管理、合约部署调用等基础操作。同时提供了多节点网络配置、常见问题解决方案以及生产环境安全建议,为开发者提供了从入门到进阶的完整指南。

分享AI、区块链技术及应用,未来已来 815

手把手教你学RDMA驱动开发专栏--第7章 队列对(QP)与数据传输实现​7.3 完成队列(CQ):事件通知机制与轮询/中断模式

本章详细探讨了RDMA驱动中完成队列(CQ)的事件通知机制,重点分析了轮询与中断两种模式的实现原理及优化策略。CQ作为操作结果的报告载体,其核心功能包括结果反馈、事件通知和资源同步。轮询模式通过主动查询实现低延迟,适合高性能场景;中断模式通过被动通知节省CPU资源,适用于低频事件处理。驱动实现需考虑CQ溢出防护、多QP共享同步等关键问题,并提供事件通道机制将CQE传递给用户态。通过对比两种模式的优缺点及适用场景,揭示了RDMA系统在性能与资源间的权衡机制。

MHD0815的博客 397

Android自定义进度条——圆角横向进度条

Android自定义进度条——圆角横向进度条1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 RectF方法的应用 onMeasure方法的应用 2.原理 画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下: 3.效果图 实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片

It一zhai男 8531

大模型——Ollama简明教程

在这篇文章中,我们将了解如何使用 Ollama、如何在 Ollama 中创建自己的模型 以及如何使用 Ollama 构建聊天机器人。这是深入研究 Ollama 的第一部分,以及我所学到的有关本地 LLM 的知识以及如何将它们用于基于推理的应用程序。在这篇文章中,你将了解——

1700

android自定义横向进度,Android自定义进度条的圆角横向进度条实例详解

1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的:invalidate()方法RectF方法的应用onMeasure方法的应用2.原理画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下:3.效果图实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的。4....

weixin_32159771的博客 429

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

进度条 横向/竖向

横向进度条。

qq_23911165的博客 694

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

android的.9图片以及圆角进度条(进度条两端都是圆角)的实现

1号黑色条位置向下覆盖的区域表示图片横向拉伸时,只拉伸该区域2号黑色条位置向右覆盖的区域表示图片纵向拉伸时,只拉伸该区域3号黑色条位置向左覆盖的区域表示图片纵向显示内容的区域4号黑色条位置向上覆盖的区域表示图片横向显示内容的区域没有黑色条的位置覆盖的区域是图片拉伸时保持不变(比如,如果图片的四角为弧形的时候,当图片被任意拉伸时,四角的弧形都不会发生改变) T...

463

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Android自定义View实现横向的双水波纹进度条

网上垂直的水波纹进度条很多,但横向的很少,将垂直的水波纹改为水平的还遇到了些麻烦,现在完善后发布出来,希望遇到的人少躺点坑。思路分析整体效果可分为三个,绘制圆角背景和圆角矩形,绘制第一条和第二条水波浪,根据自定义进度变化效果。功能实现1、绘制圆角背景和圆角矩形边框2、通过贝塞尔曲线实现双水波1)实现第一条水波moveDistance为水波垂直方向移动的距离。waveLength为水波长度,一个上弧加一个下弧为一个波长。

金戈鐡馬 1665

Android自定义圆角矩形进度条2

效果图: 或 方法讲解: (1)invalidate()方法 invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时, 调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。一般在自定义控件中会用到这个方法。 (2)RectF方法的应用 Rec...

weixin_30949361的博客 238

android横向进度条宽度,Android - 条纹进度条实现,调整view宽度仿进度条

Android自定义UIcustom view美工同学指定了一个进度条样式 这斑斓的进度条,如果要自己画实在是劳民伤财。于是请美工切了一张素材(样例)。 如果用shape或者.9图片不太好处理这个条纹。转变思路,放置2张图片。一张作为背景(底,bottom),一张作为进度条图片(cover)。 进度改变时,改变上面图片的宽度。这就要求上面的图片是圆角的。自定义ImageView,调用 canv...

weixin_42315866的博客 482

Android菜鸟练习第九课 自定义横向进度条

第一部分 在drawable中自定义progressBar的样式 xml version="1.0" encoding="utf-8"?> xmlns:android="http://schemas.android.com/apk/res/android" > android:id="@android:id/background">

进阶的菜鸟 1471

Android 自定义View ProgressBarHorizontal:横向进度条、支持圆角、渐变、图片

背景:因系统的ProgressBar设置图片时,如果图片不够大,而在大分辨率的手机上时会出现无法填充满,所以自己写一个,既修复该问题,又可方便拓展,所以抛砖引玉 功能介绍:横向进度条,分为背景与封面两层,封面与背景均支持圆角矩形、渐变、图片。

华至的博客 3025

自定义View实现横向的双水波纹进度条

网上垂直的水波纹进度条很多,但横向的很少,将垂直的水波纹改为水平的还遇到了些麻烦,现在完善后发布出来,希望遇到的人少躺点坑。 思路分析 整体效果可分为三个,绘制圆角背景和圆角矩形,绘制第一条和第二条水波浪,根据自定义进度变化效果。 功能实现 1.绘制圆角背景和圆角矩形边框 圆角矩形边框: private RectF rectBorder; if (rectBorder == null) { rectBorder = new RectF(0.5f * dp1, 0.5f * dp1, waveAct.

jingbin_的博客 612

自定义横向ProgressBar样式圆角改直角

横向progressBar的progress部分是圆角的,如果background是直角,那看起来不怎么和谐,所以这篇博文介绍progress部分改直角: 在drawable目录下新建一个:progress_style.xml 设置为0dp就是直角-->

1万+

android自定义横向进度,Android 自定义横向进度条

public class AminProgressBar extends View implements Runnable {private static final int MODE_TYPE_ROUND = 1;private static final int MODE_TYPE_SQUARE = 2;private int mWidth;private int mHeight;priv...

weixin_35974392的博客 480
上一篇: 《 Android 开发艺术探索》 View 的位置参数与使用 scrollTo/scrollBy 进行滑动
下一篇: 【Kotlin】—— 函数字面值(量)
OneDeveloper
博客等级 码龄9年 61粉丝 161原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值