Android 自定义View——圆形进度

Android自定义View——从零开始实现圆形进度条 以前老是用别人造的轮子,知其然不知其所以然,有时看懂了别人写的过多几个月又忘了,遂来开个坑把一步步实现和思路写下来,弄成一个系列。本篇只要讲的是Android自定义圆形进度条 阅读详情

很多app在刚进入app时的欢迎页后的广告页右上角有一个点击跳过的按钮,印象中好像也见过圆形的点击跳过,还有圆形进度显示,准备在项目中也加入这个效果,于是自己花点时间写了个类似效果的自定义View,先来一发效果图:
此处输入图片的描述

这个View是个圆形,且有环形进度,中心有文字进度,所以我选择继承自原始View,原理就是根据时间的流逝,计算进度,重绘View。
主要分为4个部分:

  • 自定义View属性
  • 重写OnMeasure
  • 重写OnDraw
  • 更新进度
1. 自定义View所需属性

在res/values/attr.xml中

<?xml version="1.0" encoding="utf-8"?>
<resources>


    <declare-styleable name="CustomCircleProgress">
        <attr name="centerText" format="string"/>
        <attr name="centerTextColor" format="color"/>
        <attr name="centerTextSize" format="dimension"/>
        <attr name="circleBackground" format="color" />
        <attr name="ringProgressColor" format="color"/>
        <attr name="ringProgressWidth" format="dimension"/>
        <attr name="ringProgressBackground" format="color"/>
    </declare-styleable>

    <declare-styleable name="CustomView2">
        <attr name="contentText" format="string"/>
        <attr name="contentTextColor" format="color"/>
        <attr name="contentTextSize" format="dimension"/>
    </declare-styleable>
</resources>

定义属性变量,构造方法中获取属性


/*
    * 中心文字
    * */
    private String mCenterText;
    /*
    * 中心文字颜色
    * */
    private int mCenterTextColor;
    /*
    * 中心文字大小
    * */
    private float mCenterTextSize;
    /*
    * 圆形背景
    * */
    private int mCircleBackground;
    /*
    * 圆环进度颜色
    * */
    private int mRingProgressColor;
    /*
    * 圆环进度背景颜色
    * */
    private int mRingProgressBackground;
    /*
    * 圆环进度宽度
    * */
    private float mRingProgressWidth;
     public CustomCircleProgress(Context context, AttributeSet attributeSet, int defStyleAttr){
        super(context,attributeSet,defStyleAttr);
        //        获得定义的自定义样式属性
        TypedArray a = context.obtainStyledAttributes(attributeSet,R.styleable.CustomCircleProgress,defStyleAttr,0);

        mCenterText = a.getString(R.styleable.CustomCircleProgress_centerText);
        mCenterTextColor =     a.getColor(R.styleable.CustomCircleProgress_centerTextColor,Color.WHITE);
        mCenterTextSize = a.getDimensionPixelSize(R.styleable.CustomCircleProgress_centerTextSize,(int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics()));
        mCircleBackground = a.getColor(R.styleable.CustomCircleProgress_circleBackground,Color.BLACK);

        mRingProgressColor = a.getColor(R.styleable.CustomCircleProgress_ringProgressColor,Color.GRAY);
        mRingProgressBackground = a.getColor(R.styleable.CustomCircleProgress_ringProgressBackground,Color.TRANSPARENT);
        mRingProgressWidth = a.getDimensionPixelSize(R.styleable.CustomCircleProgress_ringProgressWidth,(int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics()));

        a.recycle();
        initialize();

    }
2. 重写OnMeasure

由于继承自View,所以为了使wrap_content属性有效,必须重写OnMeasure。

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

    //如果宽或高的SpecMode为AT_MOST,就设置为默认宽高
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(mDefaultRadius,mDefaultRadius);
        }else if (widthSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(mDefaultRadius,heightSpecSize);
        }else if (heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(widthSpecSize,mDefaultRadius);
        }
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        //宽和高取较小的那一个,并设置自定义圆形View尺寸
        int mViewSize = ((height < width ? height : width));
        setMeasuredDimension(mViewSize,mViewSize);
    }
3. 重写OnDraw
@Override
    protected void onDraw(Canvas canvas) {

        //设置绘制区的矩形,为圆环外界留出圆环宽度一半的大小
        mRectFBound.set(mRingProgressWidth/2,mRingProgressWidth/2,getWidth() - mRingProgressWidth/2,getHeight() - mRingProgressWidth/2);
        mPaint.setAntiAlias(true);

//        画实心背景 半径为矩形区域减去圆环宽度的一半
        mPaint.setColor(mCircleBackground);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mRectFBound.centerX(),mRectFBound.centerY(),mRectFBound.width()/2 - mRingProgressWidth/2,mPaint);


        //画中心文字 中心文字起点为左下,文字绘制在圆形中间位置
        mPaint.setColor(mCenterTextColor);
        mPaint.setStyle(Paint.Style.FILL);
        if (mShowPercent){
            mCenterText = String.valueOf(mPercent) + "%";
        }
        mPaint.setTextSize(mCenterTextSize);
        mPaint.getTextBounds(mCenterText,0,mCenterText.length(),mTextRect);
        canvas.drawText(mCenterText,mRectFBound.centerX() - mTextRect.width()/2,mRectFBound.centerY() + mTextRect.height()/2,mPaint);

        //        画圆环   因为圆环有宽度,所以是环的中间位置与矩形四边相切
        mPaint.setStrokeWidth(mRingProgressWidth);
        mPaint.setStyle(Paint.Style.STROKE);

        mPaint.setColor(mRingProgressBackground);
        canvas.drawArc(mRectFBound,0,360,false,mPaint);

        mPaint.setColor(mRingProgressColor);
        canvas.drawArc(mRectFBound,0,mArc,false,mPaint);

        updateProgress();
    }
4. 更新进度

先定义一些更新进度需要的变量

  /*
   * 圆环起始弧度,默认360
   * */
    private int mArc = 360;

    /*
    * 当前进度
    * */
    private float mCurrProgress;


    /*
    * 进度开始时刻
    * */
    private long mStartTime ;

    /*
    * 进度是否已开始
    * */
    private boolean mStart = false;

    /**
     * 默认进度完成总时间。
     */
    private int mDuration = 3000;

    /*
    * 进度完成时间倒数
    * */
    private float mDurationReciprocal;

    /*
    * 进度是否渐增,默认是递减
    * */
    private boolean mIncreasing = false;

    /*
    * 是否显示百分比进度,默认不显示
    * */
    private boolean mShowPercent = false;
    /*
    * 百分比进度,默认100%
    * */
    private int mPercent = 100;

这里有三个变量可以在使用view的自己设定mDuration(设置进度总时间)、mIncreasing(设置进度递增或递减)、mShowPercent(是否显示进度百分比)、

 /*
    * 进度开始
    * */
    public void startRun(){
        mStartTime =  AnimationUtils.currentAnimationTimeMillis();
        mStart = true;
        mDurationReciprocal = 1.0f / (float) mDuration;
        updateProgress();
    }

     /*
    * 更新进度
    * */
    private void updateProgress(){
        if (computeProgressOffset()){

            if (mIncreasing){
                mArc = Math.round(360 * mCurrProgress);
                mPercent = Math.round(100 * mCurrProgress);
            }else {
                mArc = Math.round(360 * (1-mCurrProgress));
                mPercent = Math.round(100 * (1-mCurrProgress));
            }

            postInvalidate();
        }
    }

    /*
    * 根据时间流逝计算进度比例
    * */
    private boolean computeProgressOffset(){
        if (!mStart){
            return false;
        }
        int timePass = (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime);
        if (timePass < mDuration){
            mCurrProgress = timePass * mDurationReciprocal;
        }else {
            mStart = false;
            mCurrProgress = 1;
        }
        return true;
    }

由于是在一定的时间内更新完成进度(进度0~1),所以可以在更新进度的时候先通过 当前系统时间 - 开始更新进度时间 计算已经过去的时间timePass,这样就根据时间的流逝计算占总进度的比例,每次更新进度时调用computeProgressOffset(),判断是否完成进度,如果未完成(即时间未到),设置已完成进度,返回true,调用postInvalidate()更新View;更新完后又会调用updateProgress(),如此循环;一旦timePass超过或等于设定时间,就完成了,设置进度为1,此时仍需要更新一次,所以computeProgressOffset()仍然返回true,但更新标识mStart应为false了,以此终止更新。
这样简单的圆形进度基本功能就实现了。

Android自定义View-绘制扇形实现圆形进度 先上图,这是要实现的效果,根据音量的大小中间的进度调节。麦克风部分是透明的,所以原理就是在蒙层的底部画白色的扇形。如下图所示 这样就能实现圆形像水瓮一样的进度。 实现方法: 通过Canvas的drawArc方法实现。 public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, bo 阅读详情

相关推荐

Android自定义View进阶:创建带进度圆形进度条

自定义View是Android开发中不可或缺的高级技能,它赋予了开发者对界面的完全掌控,让我们可以创造出独特且符合特定需求的UI组件。要深入理解并熟练运用自定义View,不仅需要对Android绘图体系有清晰的认识,还要掌握自定义属性、事件处理、动画集成等关键点。本章将会带您走进Android自定义View的高级世界,帮助您从理论到实践,逐步构建出强大的自定义View组件。我们将从创建一个简单的自定义View开始,逐步深入了解并实现复杂的交互和动画效果。

weixin_31163455的博客 1125

Android自定义View——圆形进度条式按钮

介绍今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图。和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态。而且他说圆形进度的功能已经实现了。那么我们只需要对中间的两个状态做处理就行了。先来看看实现的效果图:上面说了我们只需要处理中间状态的变化就可以了,对于进度的处理直接使用了弘洋文章中实现: http://blog.youkuaiyun.com/lmj62

程序员yqy的博客 1万+

实现圆形进度条:Android自定义View高级示例

自定义View是Android开发中提升用户界面丰富性的关键技术之一。从基础的概念到复杂的动画实现,自定义View都能有效地满足开发者的各种需求。想要成功创建一个自定义View,开发者必须遵循几个核心步骤。首先,必须了解Android的绘图系统,特别是Canvas和Paint类的使用。接着,需要掌握onMeasure和onDraw等方法来测量和绘制内容。此外,自定义View时还需要处理好布局参数的设置,确保View在各种布局环境下都能正确显示。

weixin_42514750的博客 942

Android------自定义View圆形进度条2

1.首先在values下建一个attrs.xml文件                                                                         2.自定义View类 /**  * 自定义圆形进度控件  */ public class CircleProgressView extend

leehbhs的博客 516

Android自定义View:实现可拖动圆形进度条

自定义View是Android开发中一个非常重要的概念,它赋予了开发者强大的能力来创建独特且具有高度定制性的用户界面元素。通过继承已有的View类,开发者可以实现新的功能,并在应用中提供一致的用户体验。在自定义View的开发过程中,功能性扩展和自定义属性的设计是至关重要的。它们不仅提高了View的灵活性和可重用性,还增强了用户的体验。本章将深入探讨自定义属性的意义和实现方法,并展示如何扩展进度条的功能。

weixin_42581846的博客 813

Cocos2d-x手游逆向实战:Frida高阶Hook与动态解密技术

Cocos2d-x作为主流跨平台游戏引擎,其混合架构(C++核心+JNI桥接+Lua/JS脚本)和强加固策略(符号剥离、anti-frida、so加壳)使传统逆向方法失效。本文围绕‘无符号定位’‘C++函数硬编码地址识别’‘Lua层AST级劫持’‘OpenGL内存回溯解密’四大关键技术展开,深入解析如何在真实上线项目中稳定hook被strip的libcocos2d.so关键函数、绕过反调试心跳检测、从glTexImage2D参数逆向追踪明文资源,并结合熵值扫描实现零先验知识的内存明文发现。面向已掌握Frid

weixin_30345577的博客 675

一些“跳过”按钮及缓冲框示例

前言  最近自定义控件的实践相对多一些,看到了别人app上实现的效果就想自己动手尝试下,看自己能不能做到。本文是对一些app第一个页面的“跳过”按钮及一些缓冲框的实现。一个控件就详细写一篇文,未免过于麻烦,所以这里是做了一个汇总,只写核心思路及相关伪代码,几个控件写成一篇。后面会给出完整代码。1. 矩形倒计时“跳过”  1. 先来看一下最终效果:  2. 基本思路及相关代码  首先,我们看到“跳过”

yizhan_zjz的博客 1615

Mac Studio M5 Ultra本地部署大模型实战:从内存原理到Ollama开发工作流

大模型推理的性能瓶颈往往不在算力,而在于内存能否装下整个模型、带宽能否持续供得上。Transformer架构每生成一个token都需要把权重完整扫一遍,决定了这本质上是内存密集型任务——统一内存架构因此成为本地部署的关键通路,超大容量与高带宽并行,让“装得下”和“跑得快”同时成立。模型量化技术(如Q4_K_M)则是另一项决定性软件策略,用轻微精度损失换取更低的硬件门槛,也是Ollama本地部署从7B到70B各类模型必做的前置功课。当本地推理服务跑起来后,借助VS Code等开发工具的OpenAI兼容API接

weixin_29043895的博客 454

【Android进度条】三种方式实现自定义圆形进度条ProgressBar

一、通过动画实现定义res/anim/loading.xml如下:&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;animation-list android:oneshot="false" xmlns:android="http://schemas.android.com/apk/res/android"&gt; &lt;item

mmdev 469

Arduino MLX90393磁力计驱动库:高精度三轴霍尔传感器开发指南

三轴霍尔效应磁力计是嵌入式系统中实现无接触角度检测、电子罗盘与电流传感的核心器件。其工作原理基于霍尔电压随外磁场矢量变化的物理特性,通过I²C接口输出高分辨率(16/20-bit)XYZ轴原始数据,并集成温度补偿与数字滤波功能。技术价值体现在确定性响应、低功耗(典型0.5 μA待机)及强抗干扰能力,适用于电池供电设备与实时操作系统环境。典型应用场景包括电机位置反馈、永磁体旋转角度解算、工业编码器和地磁导航。本库专为Arduino生态优化,深度封装MLX90393寄存器协议与自校准流程,同时兼容STM32、E

weixin_29363791的博客 642

034、MLCA 多尺度局部上下文注意力的 YOLOv11 适配:轻量级金字塔式空间上下文聚合

本文介绍了一种将多尺度局部上下文注意力(MLCA)模块集成到YOLOv11模型中的方法,以解决小目标检测中空间信息丢失的问题。MLCA采用金字塔式局部上下文聚合策略,通过不重叠的网格划分实现轻量级空间注意力计算,相比全局注意力机制能更好地保留小目标特征。 作者详细记录了实现过程,包括模块定义、参数调优和训练技巧,特别指出避免使用BN而改用GroupNorm以提升训练稳定性。在VisDrone数据集上的实验表明,MLCA-YOLOv11在参数量和计算量基本不变的情况下,mAP提升2.5%,其中行人检测提升3.

sundong_81的博客 279

Android 自定义View之圆形进度条

需求是不停的,会有这些需求:可指定画笔(宽度、颜色等)、可指定动画时长等。这些可以通过创建 Java 接口来设置,但我要学自定义View,就要用attr。未完待续~~Android Canvas的drawText()和文字居中方案。

weixin_44021334的博客 6224

【WorkBuddy专栏51】Codex与WorkBuddy的底层基因——两条完全不同的AI智能体路线(上)

【WorkBuddy专栏51】Codex与WorkBuddy的底层基因——两条完全不同的AI智能体路线(上)

AI人人懂 2181

Android:自定义View实现绚丽的圆形进度条

Android:自定义View实现绚丽的圆形进度条

books1958的专栏 8706

Android 10.0 SystemUI 屏蔽状态栏消息推送弹出的悬浮通知

在状态栏中,有一些通知类似 消息推送 弹出的 悬浮通知,弹出30秒之后会消失掉 要想屏蔽掉这些通知,首选知道这些通知是怎么产生的 通知类型 NotificationContentInflater.java 详细的介绍各种通知的类型 frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java /** * The defau

安卓兼职framework和app工程师的博客 1542

北斗导航 | 卡尔曼滤波与因子图优化对比(附图优化matlab代码)

- 历史数据利用:因子图通过滑动窗口保留历史状态,优化时联合多帧数据;卡尔曼滤波仅依赖当前和上一帧状态 。 - 迭代优化:因子图通过多次迭代逼近最优解,卡尔曼滤波仅单次更新 。 - 误差抑制:因子图的多次线性化可有效抑制非线性误差(如GNSS伪距观测的非线性) 。

尘世冰封的专栏 1303

Android自定义View之圆形进度条

Android自定义View之圆形进度条尽管github上的开源圆形进度条已经很多了,但是我仍然希望能通过自己完成一个,接下来我就一步一步实现圆形进度条,今天我们要实现的效果图如下: 观察上面两幅图我们可以看到,这个图形是由两部分组成的中间的圆形+外围的弧形,我们自然而然的想到了用canvas画。想好就开始实践, 新建PercentDigitalView项目,新建view包,新建Perc

小海编码日记 676

【云原生技术】K8s 在拉取镜像时报错tls: failed to verify certificate: x509: certificate signed by unknown authority

原因 Kubernetes 节点在拉取镜像时会对 Harbor 的 HTTPS 证书做严格校验; 日志里的核心报错是: ``` tls: failed to verify certificate: x509: certificate signed by unknown authority ``` 说明 Harbor 返回的服务器证书要么是自签发,要么缺少在系统信任链里的根/中级 CA,节点因此拒绝连接。 你需要让 **所有负责拉镜像的节点(containerd 或 Docker 守护进程)

weixin_46453070的博客 2875

Android 自定义View实现圆形加载进度条

Android 自定义view圆形加载进度条

Android_Gt 3477

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Android自定义view实现圆形进度条更新

Android自定义view实现圆形进度条更新准备期实现自定义ViewService主Activitylayout布局最终实现效果 刚回顾完群英传的自定义view章节,在3.6.3.1中弧形展示图,看完在想,做成加载进度条是否稍微有趣点呢,就着手开始实现了。先看下弧形展示图。 准备期 有了需求,那么就得先思考如何实现,开启线程,自加后更新数据?还是开个服务再返回更新呢?我选择后者,作为小白,多拓...

J1036767889的博客 484

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

android绘制环形进度_Android 自定义 View 之圆形进度条总结

原标题:Android 自定义 View 之圆形进度条总结最近撸了一个圆形进度条的开源项目,算是第一次完完整整的使用自定义 View 。在此对项目开发思路做个小结,欢迎大家 Star 和 Fork该项目总共实现了三种圆形进度条效果CircleProgress:圆形进度条,可以实现仿 QQ 健康计步器的效果,支持配置进度条背景色、宽度、起始角度,支持进度条渐变DialProgress:类似 Circ...

weixin_39888412的博客 418

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Android自定义View-圆形进度条

好几天不写博客了,这段时间一直没时间,感觉一直在忙,但是进度不大。 好了,言归正传,最近项目里要用到这么一个自定义view,是一个圆形的进度圆环,现在学习下怎么来自定义它。 源码下载地址https://github.com/baojie0327/ViewAndGroup自定义之前先分析一下,这个自定义View主要有以下几个部分组成: - 最外层的圆环 - 圆环上的小圆点,会随着进度移动 -

香蕉你个不呐呐的博客 582

Android自定义View之圆形比例图(进度条)

在我们APP中,经常会用到如下的一张比例图:                                                      这个比例图可以清楚的展示一个项目所占的比例,同时也可以变成一个圆形进度条:

isJoker的博客 1834

Android自定义view实现圆形进度条

Android自定义view实现圆形进度条

吐尔洪江 2530

android自定义view之半圆形进度条

安卓自定义VIEW之半圆进度条

baidu_34934230的博客 3157

安卓进阶之路:自定义View圆形进度条源码解析

安卓进阶之路:自定义View圆形进度条源码解析 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在Android开发中,自定义View是区分普通开发者与高手的重要技能之一。今天,我们介绍的开源项目——自定义View,自定义属性(带进度的圆形进度条)源码,是一个非常适合进阶学习的资源。该源码提供了一种新颖的进度展示方式,让应用界面更加直观和美观。 项目技术分析 项目基于A...

gitblog_06724的博客 270
github_35205464
博客等级 码龄10年 0粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值