1. 程式人生 > >自定義View之簡單自定義圓形進度條

自定義View之簡單自定義圓形進度條

達到的效果如下:
這裡寫圖片描述

從上面的效果可以看出,主要有以下幾個自定義屬性:
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);
  }
}

這樣就完成了一個簡單的圓形進度條的自定義。