Android知识学习区iOS分享的demo

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

2016-08-25  本文已影响953人  hongjay

昨天简单熟悉了下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);
       }
   }

自定义属性


为控件添加自定义属性的几个步骤。
  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

上一篇下一篇

猜你喜欢

热点阅读