自定义View之简单自定义圆形进度条

来源:互联网 发布:adobe reader xi mac 编辑:程序博客网 时间:2024/04/26 19:37

达到的效果如下:
这里写图片描述

从上面的效果可以看出,主要有以下几个自定义属性:
1、背景颜色
2、进度扇形颜色
3、半径
4、起始角度
因此,在attrs.xml中定义如下属性:

<?xml version="1.0" encoding="utf-8"?><resources>  <declare-styleable name="SimpleRoundProgressBar">    <attr format="color" name="roundColor"/>    <attr format="color" name="roundProgressColor"/>    <attr format="dimension" name="circleRadius"/>    <attr format="integer" name="startAngle"/>  </declare-styleable></resources>

下面是SimpleRoundProgressBar代码,在onMeasure当中确定view的大小,在onDraw来进行绘制。

package com.easyliu.demo.customizeview;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.view.View;/** * Created by easyliu on 2017/2/24. */public class SimpleRoundProgressBar extends View {  private Paint mPaint;//画笔  private RectF mRectF;//扇形绘制的矩形范围  private int mRoundColor;//圆环的颜色  private int mRoundProgressColor; //进度条的颜色  private float mRadius;//半径  private int mWidth;  //宽度  private int mHeight; //高度  private int mCenterX; //中心X坐标  private int mCenterY; //中心Y坐标  private int mStartAngle; //初始角度  private int mSweepAngle; //扫过的角度  private static final int DEFAULT_INIT_ANGLE = 0;//默认的初始化角度  private static final int DEFAULT_RADIUS = 10;//默认的半径  public SimpleRoundProgressBar(Context context) {    this(context, null);  }  public SimpleRoundProgressBar(Context context, AttributeSet attrs) {    this(context, attrs, 0);  }  public SimpleRoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    mPaint = new Paint();    mRectF = new RectF();    TypedArray typedArray =        context.obtainStyledAttributes(attrs, R.styleable.SimpleRoundProgressBar);    mRoundColor = typedArray.getColor(R.styleable.SimpleRoundProgressBar_roundColor, Color.GRAY);    mRoundProgressColor =        typedArray.getColor(R.styleable.SimpleRoundProgressBar_roundProgressColor, Color.RED);    mRadius =        typedArray.getDimension(R.styleable.SimpleRoundProgressBar_circleRadius, DEFAULT_RADIUS);    mStartAngle =        typedArray.getInteger(R.styleable.SimpleRoundProgressBar_startAngle, DEFAULT_INIT_ANGLE);    typedArray.recycle();  }  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    //获取测量模式    int widthMode = MeasureSpec.getMode(widthMeasureSpec);    int heightMode = MeasureSpec.getMode(heightMeasureSpec);    //获取测量大小    int widthSize = MeasureSpec.getSize(widthMeasureSpec);    int heightSize = MeasureSpec.getSize(heightMeasureSpec);    //如果为确定值    if (heightMode == MeasureSpec.EXACTLY) {      mHeight = heightSize;    } else {      //如果为wrap_content,高度为半径大小乘以2,注意padding      mHeight = (int) (mRadius * 2) + getPaddingTop() + getPaddingBottom();    }    //如果为确定值    if (widthMode == MeasureSpec.EXACTLY) {      mWidth = widthSize;      mHeight=mWidth;//宽和高相等    } else {      //如果为wrap_content,宽度为半径大小乘以2,注意padding      mWidth = (int) (mRadius * 2) + getPaddingLeft() + getPaddingRight();    }    //设置视图的大小    setMeasuredDimension(mWidth, mHeight);  }  @Override protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    mPaint.setColor(mRoundColor);    mPaint.setAntiAlias(true);    mCenterX = mWidth / 2;    mCenterY = mHeight / 2;    //注意处理padding    mRadius = (mWidth - getPaddingLeft() - getPaddingRight()) / 2;    //画圆    canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);    mPaint.setColor(mRoundProgressColor);    //注意处理padding    mRectF.left = getPaddingLeft();    mRectF.right = mWidth - getPaddingRight();    mRectF.top = getPaddingTop();    mRectF.bottom = mHeight - getPaddingBottom();    //画扇形    canvas.drawArc(mRectF, (float) mStartAngle, mSweepAngle, true, mPaint);  }  public int getRoundColor() {    return mRoundColor;  }  public void setRoundColor(int roundColor) {    this.mRoundColor = roundColor;  }  /**   * 得到初始角度   */  public synchronized int getStartAngle() {    return mStartAngle;  }  /**   * 设置初始角度   */  public synchronized void setStartAngle(int startAngle) {    if (startAngle < -360) {      throw new IllegalArgumentException("the angle can not less than -360");    }    if (startAngle > 360) {      throw new IllegalArgumentException("the angle can not larger than 360");    }    this.mStartAngle = startAngle;  }  /**   * 得到扫过的角度   */  public synchronized int getSweepAngle() {    return mSweepAngle;  }  /**   * 设置扫过的角度,相对于起始点   *   * @param sweepAngle 0~360   */  public synchronized void setSweepAngle(int sweepAngle) {    if (sweepAngle < 0) {      throw new IllegalArgumentException("the angle can not less than 0");    }    if (sweepAngle > 360) {      throw new IllegalArgumentException("the angle can not larger than 360");    }    this.mSweepAngle = sweepAngle;    postInvalidate();  }}

定义好了之后就可以使用了,首先是xml文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:easyliu="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.easyliu.demo.customizeview.RoundProgressBarActivity"    >  <com.easyliu.demo.customizeview.SimpleRoundProgressBar      android:id="@+id/progress_demo"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:layout_centerHorizontal="true"      android:padding="10dp"      easyliu:circleRadius="50dp"      easyliu:roundColor="#5F000000"      easyliu:roundProgressColor="#ff8d33"      />  <com.easyliu.demo.customizeview.SimpleRoundProgressBar      android:id="@+id/progress_demo2"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:layout_centerHorizontal="true"      android:layout_below="@id/progress_demo"      android:padding="10dp"      easyliu:circleRadius="60dp"      easyliu:roundColor="@color/colorPrimary"      easyliu:roundProgressColor="@color/colorAccent"      /></RelativeLayout>

然后是Activity代码,在代码中使用定时器来定时更新进度即可。

package com.easyliu.demo.customizeview;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import java.util.Timer;import java.util.TimerTask;public class RoundProgressBarActivity extends AppCompatActivity {  private int mCurrentAngle = 0;  private SimpleRoundProgressBar mRoundProgressBar1;  private SimpleRoundProgressBar mRoundProgressBar2;  @Override protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_progress_bar);    initViews();    Timer timer = new Timer();    timer.schedule(new TimerTask() {      @Override public void run() {        mCurrentAngle++;        mRoundProgressBar1.setSweepAngle(mCurrentAngle);        mRoundProgressBar2.setSweepAngle(mCurrentAngle);        if (mCurrentAngle >= 360) {          mCurrentAngle = 0;        }      }    }, 0, 20);  }  private void initViews(){    mRoundProgressBar1 =        (SimpleRoundProgressBar) findViewById(R.id.progress_demo);    mRoundProgressBar1.setStartAngle(-90);    mRoundProgressBar2= (SimpleRoundProgressBar) findViewById(R.id.progress_demo2);    mRoundProgressBar2.setStartAngle(0);  }}

这样就完成了一个简单的圆形进度条的自定义。

0 0