完全自定义控件-简单环形进度条制作

昨天简单熟悉了下canvas的API,今天来做个小demo巩固下
回顾完全自定义控件-Canvas之绘制基本形状

简单环形进度条制作

本文实现一个自定义的加载进度条,效果如下图所示:

效果

实现步骤:


  1. 新建CircleProgressView类继承View
  2. 在构造函数中初始化画笔
private void init() {
       mPaint = new Paint();
       mPaint.setColor(Color.BLACK);
       mPaint.setStyle(Paint.Style.STROKE);//绘图为描边模式
       mPaint.setStrokeWidth(20);//画笔宽度
       mPaint.setAntiAlias(true);//抗锯齿
   }

  1. 重写onDraw
    主要逻辑为先绘制一个圆环,然后在它上面根据进度来绘制圆弧
//进度
private int mProgress;
//是否到下一圈
private boolean mChanged;
protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       //得到画布一半的宽度
       int center = getWidth() / 2;
       //定义圆的半径
       int radius = 100;
       //定义一个圆
       mRectF = new RectF(center - radius, center - radius, center + radius, center + radius);
       if (!mChanged) {
           //设置画笔的颜色
           mPaint.setColor(Color.BLUE);
           //画一个圆,由于画笔是描边模式,所以展现的是个圆环
           canvas.drawCircle(center, center, radius, mPaint);
           //设置画笔的颜色
           mPaint.setColor(Color.RED);
           //绘制圆弧,从12点方向(-90度)开始绘制,偏移角度为进度
           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);
       } else {
           mPaint.setColor(Color.RED);
           canvas.drawCircle(center, center, radius, mPaint);
           mPaint.setColor(Color.BLUE);
           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);
       }
       //进度更新方法
       startProgress();
   }

进度更新方法

private void startProgress() {
       //当view控件可见时,每50毫秒更新一次视图
       if (isShown()) {
           postDelayed(new Runnable() {
               @Override
               public void run() {
                   mProgress += 10;
                   //如果偏移角度超过360,则至为0,并且跟换绘制颜色
                   if (mProgress >= 360) {
                       mProgress = 0;
                       mChanged = !mChanged;
                   }

                  //请求重绘View树,调用draw()方法
                   invalidate();
               }
           }, 50);
       }
   }

自定义属性


  • 很明显,我们不可能在代码中写死控件的参数,我们需要提供一些可定制属性,方便在XML布局文件中对控件进行设置。
为控件添加自定义属性的几个步骤。
  1. 在values目录下新建一个attrs.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <declare-styleable name="CircleProgressView">
       <attr name="firstColor" format="color"/> <!--圆环颜色-->
       <attr name="secondColor" format="color"/> <!--圆环颜色-->
       <attr name="circleWidth" format="dimension"/><!--色带宽度-->
   </declare-styleable>
</resources>

不同的属性对应不同的format,属性对应的format可以参考
http://blog.csdn.net/pgalxx/article/details/6766677

  1. 获取属性
    在CircleProgressView的构造方法中获取布局文件中的属性
//获取TypedArray
context.obtainStyledAttributes(attrs,R.styleable.RoundProgressBar)

然后从TypedArray获取我们定义的属性

public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
       super(context, attrs, defStyleAttr);
       TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView, defStyleAttr, 0);

       //获取自定义属性和默认值
       //getColor方法的第一个参数是我们在XML文件中定义的颜色,如果我们没有给我们自定义的View定义颜色,他就会使用第二个参数中的默认值
       mFirstColor = ta.getColor(R.styleable.CircleProgressView_firstColor, Color.RED);
       mSecondColor = ta.getColor(R.styleable.CircleProgressView_secondColor, Color.BLUE);
       mCircleWidth = ta.getDimensionPixelSize(R.styleable.CircleProgressView_circleWidth,
               (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()));
       
       //释放该实例,从而使其可被其他模块复用
       ta.recycle();
       init();
   }

  1. 在onDraw()中使用
protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       //得到画布一半的宽度
       int center = getWidth() / 4;
       //定义圆的半径
       int radius = 100;
       //定义一个圆
       mRectF = new RectF(center - radius, center - radius, center + radius, center + radius);
       if (!mChanged) {
           //设置画笔的颜色
           mPaint.setColor(mFirstColor);
           //画一个圆,由于画笔是描边模式,所以展现的是个圆环
           canvas.drawCircle(center, center, radius, mPaint);
           //设置画笔的颜色
           mPaint.setColor(mSecondColor);
           //绘制圆弧,从12点方向(-90度)开始绘制,偏移角度为进度
           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);
       } else {
           mPaint.setColor(mSecondColor);
           canvas.drawCircle(center, center, radius, mPaint);
           mPaint.setColor(mFirstColor);
           canvas.drawArc(mRectF, -90, mProgress, false, mPaint);
       }
       //进度更新方法
       startProgress();
   }

  1. 在布局中使用
    第二个控件使用了自定义属性
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   tools:context="zhj.progressbardemo.MainActivity">

   <zhj.progressbardemo.CircleProgressView
       android:layout_width="match_parent"
       android:layout_height="259dp"
       />

   <zhj.progressbardemo.CircleProgressView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_marginTop="50dp"
       app:circleWidth="30dp"
       app:firstColor="#f58a47"
       app:secondColor="#5be9d8"
       />
</LinearLayout>

效果展示

效果

这里是项目地址

参考
https://segmentfault.com/a/1190000004624339
http://blog.csdn.net/lmj623565791/article/details/24500107

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

推荐阅读更多精彩内容