Android环形进度条

分享一个环形进度条供大家参考,项目地址

https://download.csdn.net/download/weixin_40998254/10595267

效果如图

image

下面是该自定义进度条的代码,目前属于简陋版本,不过注释很详细,方便扩展。

首先是自定View的代码

/**
 * 作者:GJP on 2018/7/26 15:12
 * 邮箱:xiaoxiao9575@126.com
 * 描述:
 */

public class CircularProgressView extends View {

    private Context mContext;
    private Paint mPaint;
    private int mProgress = 0;
    private static int MAX_PROGRESS = 100;
    /** * 弧度 */
    private int mAngle;
    /** * 中间的文字 */
    private String mText;
    /** * 外圆颜色 */
    private int outRoundColor;
    /** * 内圆的颜色 */
    private int inRoundColor;
    /** * 线的宽度 */
    private int roundWidth;
    private int style;
    /*** 字体颜色*/
    private int textColor;
    /** * 字体大小 */
    private float textSize;
    /** * 字体是否加粗 */
    private boolean isBold;
    /** * 进度条颜色 */
    private int progressBarColor;

    public CircularProgressView(Context context) {
        this(context, null);
    }
    public CircularProgressView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public CircularProgressView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);
        mContext = context;
        init(attrs);
    }

    @TargetApi(21)
    public CircularProgressView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mContext = context;
        init(attrs);
    }

    /**
     * 解析自定义属性
     * @param attrs
     */
    public void init(AttributeSet attrs) {
        mPaint = new Paint();
        TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar);
        outRoundColor = typedArray.getColor(R.styleable.CircleProgressBar_outCircleColor, getResources().getColor(R.color.colorPrimary));
        inRoundColor = typedArray.getColor(R.styleable.CircleProgressBar_inCircleColor, getResources().getColor(R.color.colorPrimaryDark));
        progressBarColor = typedArray.getColor(R.styleable.CircleProgressBar_progressColor, getResources().getColor(R.color.colorAccent));
        isBold = typedArray.getBoolean(R.styleable.CircleProgressBar_textBold, false);
        textColor = typedArray.getColor(R.styleable.CircleProgressBar_textColor, Color.BLACK);
        roundWidth = typedArray.getDimensionPixelOffset(R.styleable.CircleProgressBar_lineWidth, 20);
        typedArray.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) { /** * 画外圆 */
        super.onDraw(canvas);
        int center = getWidth() / 2;//圆心
        int radius = (center - roundWidth / 2);// 半径

        mPaint.setColor(outRoundColor); //外圆颜色
        mPaint.setStrokeWidth(roundWidth); //线的宽度
        mPaint.setStyle(Paint.Style.STROKE); //空心圆
        mPaint.setAntiAlias(true); //消除锯齿
        canvas.drawCircle(center, center, radius, mPaint); //内圆

        mPaint.setColor(inRoundColor);
        radius = radius - roundWidth;
        canvas.drawCircle(center, center, radius, mPaint); //画进度是一个弧线

        mPaint.setColor(progressBarColor);
        RectF rectF = new RectF(center - radius, center - radius, center + radius, center + radius);//圆弧范围的外接矩形
        canvas.drawArc(rectF, -90, mAngle, false, mPaint);

        canvas.save(); //平移画布之前保存之前画的

        // 画进度终点的小球,旋转画布的方式实现
        mPaint.setStyle(Paint.Style.FILL);
        // 将画布坐标原点移动至圆心
        canvas.translate(center, center);
        // 旋转和进度相同的角度,因为进度是从-90度开始的所以-90度
        canvas.rotate(mAngle - 90);
        // 同理从圆心出发直接将原点平移至要画小球的位置
        canvas.translate(radius, 0);
        canvas.drawCircle(0, 0, roundWidth, mPaint);

        // 画完之后恢复画布坐标
        canvas.restore();

        // 画文字将坐标平移至圆心
        canvas.translate(center, center);
        mPaint.setStrokeWidth(0);
        mPaint.setColor(textColor);
        if (isBold) { //字体加粗
            mPaint.setTypeface(Typeface.DEFAULT_BOLD);
        } if (!TextUtils.isEmpty(mText)) {
            // 动态设置文字长为圆半径,计算字体大小
            float textLength = mText.length();
            textSize = radius / textLength;
            mPaint.setTextSize(textSize);
            // 将文字画到中间
            float textWidth = mPaint.measureText(mText);
            canvas.drawText(mText, -textWidth / 2, textSize / 2, mPaint);
        }

    }

    public int getProgress() {
        return mProgress;
    }

    /**
     * 设置进度
     * @return
     */
    public void setProgress(int p) {
        if (p > MAX_PROGRESS) {
            mProgress = MAX_PROGRESS;
            mAngle = 360;
        } else {
            mProgress = p;
            mAngle = 360 * p / MAX_PROGRESS;
        }
        //更新画布
        invalidate();
    }

    public String getText() {
        return mText;
    }

    /**
     * 设置文本
     * @param mText
     */
    public void setText(String mText) {
        this.mText = mText;
        invalidate();
    }

}

styles.xml中需要添加

<declare-styleable name="CircleProgressBar">
        <attr name="outCircleColor" format="color"></attr>
        <attr name="inCircleColor" format="color"></attr>
        <attr name="progressColor" format="color"></attr>
        <attr name="textColor" format="color"></attr>
        <attr name="textBold" format="boolean"></attr>
        <attr name="lineWidth" format="dimension"></attr>
</declare-styleable>

再布局文件中引用的示例代码

<com.xiaoxiao9575.circularprogressapplication.CircularProgressView
        android:id="@+id/progress_bar"
        android:layout_centerInParent="true"
        android:layout_centerHorizontal="true"
        android:layout_width="150dp"
        android:layout_height="150dp"
        app:inCircleColor="#DCDCDC"
        app:outCircleColor="#F0F0F0"
        app:progressColor="#50CE7B"
        app:textBold="true"
        app:textColor="#50CE7B"
        app:lineWidth="5dp" />

Activity中具体控制进度

public class MainActivity extends AppCompatActivity {

    private CircularProgressView progress_bar;
    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            progress_bar.setProgress(msg.what);
            progress_bar.setText(progress_bar.getProgress()+"%");
            addProgress(msg.what);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        progress_bar = (CircularProgressView) findViewById(R.id.progress_bar);
        progress_bar.setProgress(0);
        progress_bar.setText(progress_bar.getProgress()+"%");
        addProgress(0);
    }

    private void addProgress(int i) {
        if (i>=100){
            i = 0;
        }else {
            ++i;
        }
        handler.sendEmptyMessageDelayed(i, 100);
    }

}

关于这个自定义的环形进度条没什么说的,代码注释很详细,使用方法都粘贴出来了,因为扩展起来很方便所以粘贴出来供大家参考和自己留作记录,如果有时间后续会发一个完善些的圆形进度条到GitHub上。

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

推荐阅读更多精彩内容

  • 环形进度条 如上图所示,之所以想到写这个,因为项目中有这样的需求,所以自己就去琢磨琢磨该怎么去实现这个需求。实现思...
    Kotyo阅读 1,395评论 0 2
  • 第326期 盈利模式9.0浓缩MBA 上午 盈利模式 ——实现——高增长、高盈利 1. 战略设计 2. 产品战略 ...
    ywq5084阅读 375评论 1 1
  • “老金,你前些日子穿越到古代去干啥了?” 老金苦笑一声,“哎,别提这破事,本想着去八珍阁吃那八珍玉食,没成想遇见个...
    7默阅读 489评论 0 0
  • 妈累了倦了离开土乡, 妈独自远行去了天堂。 我撕心裂肺喊一声“娘”, 爱的善念一生的沧桑。 你入土埋葬大地苍凉, ...
    咪咪139318阅读 312评论 1 15
  • 我看我在APP上立的flag什么时候兑现呢。今天没有心情想故事了。 这个是有点灵感来源,可能会有炒饭嫌疑。 穆...
    舟海的海啊阅读 131评论 0 1