Android · 2015年3月31日 0

Android自定义控件系列之应用篇——圆形进度条

一、概述

在上一篇博文中,我们给大家介绍了Android自定义控件系列的基础篇。链接: http://www.cnblogs.com/jerehedu/p/4360066.html

这一篇博文中,我们将在基础篇的基础上,再通过重写ondraw()方法和自定义属性实现圆形进度条,效果如图所示:

二、实现步骤

1、  编写自定义组件MyCircleProgress扩展View

public class MyCircleProgress extends View {
…    
}

2、  在MyCircleProgress类中,定制属性

public int progress  = 0;//进度实际值,当前进度
  /**
   * 自定义控件属性,可灵活的设置圆形进度条的大小、颜色、类型等
   */
  private int mR;//圆半径,决定圆大小
  private int bgColor;//圆或弧的背景颜色
  private int fgColor;//圆或弧的前景颜色,即绘制时的颜色
  private int drawStyle; //绘制类型 FILL画圆形进度条,STROKE绘制弧形进度条
      private int strokeWidth;//STROKE绘制弧形的弧线的宽度
  private int max;//最大值,设置进度的最大值
/** 
   * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步 
   */  
  public synchronized void setProgress(int progress) {
    if(progress<0){
      progress=0;
    }else if(progress>max){
      progress=max;
    }else{
      this.progress = progress;
    }		
  }
  public int getMax() {
    return max;	}

3、  为定制的属性编写attrs.xml资源,该资源文件放在res/values目录下,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="CircleProgressBar">
    <attr name="bgColor" format="color"/>
    <attr name="fgColor" format="color"/>
    <attr name="r" format="integer"/>
    <attr name="strokeWidth" format="integer"/>
    <attr name="drawStyle">
      <enum name="STROKE" value="0"></enum>
      <enum name="FILL" value="1"></enum>
    </attr>
    <attr name="max" format="integer"/>
  </declare-styleable>
</resources>

4、  在MyCircleProgress类中定义构造函数,初始化属性

private void initProperty(AttributeSet attrs){
  TypedArray tArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar);
    mR=tArray.getInteger(R.styleable.CircleProgressBar_r,10);
    bgColor=tArray.getColor(R.styleable.CircleProgressBar_bgColor, Color.GRAY);
    fgColor=tArray.getColor(R.styleable.CircleProgressBar_fgColor, Color.RED);
    drawStyle=tArray.getInt(R.styleable.CircleProgressBar_drawStyle, 0);
    strokeWidth=tArray.getInteger(R.styleable.CircleProgressBar_strokeWidth, 10);
    max=tArray.getInteger(R.styleable.CircleProgressBar_max, 100);
  }	
public MyCircleProgress(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    this.paint = new Paint();
    this.paint.setAntiAlias(true); // 消除锯齿
    this.paint.setStyle(Style.STROKE); // 绘制空心圆或 空心矩形
    initProperty(attrs);	
  }

5、  在MainActivity中布局文件中添加MyCircleProgress组件,如下所示

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res/com.jereh.mydrawcircleprogress"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
     >   
 <com.jereh.views.MyCircleProgress
   android:id="@+id/MyCircleProgress"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content" 
   app:r="45"
   app:strokeWidth="10"
   app:bgColor="#cccccc"
   app:fgColor="#ff0000"
   app:drawStyle="FILL"
   app:max="50"
   />
</RelativeLayout>

6、  自定义组件MyCircleProgress中重写onDraw方法:

protected  void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  int center = getWidth() / 2; // 圆心位置
  this.paint.setColor(bgColor);
  this.paint.setStrokeWidth(strokeWidth);
  canvas.drawCircle(center, center, mR, this.paint);
  // 绘制圆环
  this.paint.setColor(fgColor);
  if(drawStyle==0){
    this.paint.setStyle(Style.STROKE);
    opt=false;
  }else{
    this.paint.setStyle(Style.FILL);
    opt=true;
  }
  int top = (center - mR);
  int bottom = (center + mR);
  RectF oval = new RectF(top, top, bottom, bottom);
  canvas.drawArc(oval, 270, 360*progress/max, opt, paint);
} 

7、编写MainActivity

public class MainActivity extends Activity {
  private MyCircleProgress progressView;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    progressView = (MyCircleProgress) findViewById(R.id.MyCircleProgress);
    new ProgressAnimation().execute();
  }
  class ProgressAnimation extends AsyncTask<Void, Integer, Void> {
    @Override
    protected Void doInBackground(Void... params) {
      //进度值不断的变化
      for (int i = 0; i < progressView.getMax(); i++) {
        try {
          publishProgress(i);
          Thread.sleep(100);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      return null;
    }
    @Override
    protected void onProgressUpdate(Integer... values) {
      //更新进度值
      progressView.setProgress(values[0]);
      progressView.invalidate();
      super.onProgressUpdate(values);
    }
  }
}

Share this: