1. 程式人生 > >Android 圓形進度條

Android 圓形進度條

這裡寫圖片描述

  • 目錄結構
    這裡寫圖片描述

  • 核心程式碼CicleProgressView.java

public class CircleProgressView extends View {

    /**
     * 背景顏色
     */
    private int backgroundColor;
    /**
     * 前景顏色
     */
    private int foregroundColor;
    /**
     * 進度條顏色
     */
    private int progressColor;
    /**
     * 字型顏色
     */
    private
int fontColor; /** * 當前進度 */ private int currentProgress = 0; /** * 最大進度 */ private int maxProgress; /** * 畫筆 */ private Paint mPaint = new Paint(); /** * 半徑長 */ private int mRadius; /** * 進度寬 */ private int progressWidth; /** * 字型大小 */
private int textSize; /** * 回撥監聽 */ private ProgressedListener listener; public CircleProgressView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView); backgroundColor = a.getColor(R.styleable.CircleProgressView_circleprogress_backgroundcolor, Color.WHITE); foregroundColor = a.getColor(R.styleable.CircleProgressView_circleprogress_foregroundcolor, Color.WHITE); progressColor = a.getColor(R.styleable.CircleProgressView_circleprogress_progresscolor, Color.BLUE); fontColor = a.getColor(R.styleable.CircleProgressView_circleprogress_fontcolor, Color.BLUE); maxProgress = a.getInteger(R.styleable.CircleProgressView_circleprogress_maxprogress, 100
); progressWidth = a.getInteger(R.styleable.CircleProgressView_circleprogress_width, 10); textSize = a.getInteger(R.styleable.CircleProgressView_circleprogress_textsize, 10); a.recycle();//釋放資源 mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); // int widthSize = MeasureSpec.getSize(widthMeasureSpec); // int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(200, 200); } else if (widthSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(heightMeasureSpec, heightMeasureSpec); } else if (heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthMeasureSpec, widthMeasureSpec); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (w > h) { mRadius = h / 2; } else { mRadius = w / 2; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(backgroundColor); canvas.drawCircle(getWidth() / 2, getHeight() / 2, mRadius, mPaint);//畫最下邊的圓 mPaint.setColor(progressColor); canvas.drawArc(getWidth() / 2 - mRadius, getHeight() / 2 - mRadius, getWidth() / 2 + mRadius, getHeight() / 2 + mRadius, -90, 360 * (((float) currentProgress) / maxProgress), true, mPaint);//畫扇形 mPaint.setColor(foregroundColor); canvas.drawCircle(getWidth() / 2, getHeight() / 2, mRadius - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, progressWidth, getResources().getDisplayMetrics()), mPaint);//畫中心圓 mPaint.setColor(fontColor); mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, textSize, getResources().getDisplayMetrics())); String text = currentProgress + "%"; canvas.drawText(text, getWidth() / 2 - mPaint.measureText(text) / 2, getHeight() / 2 + mPaint.measureText("%") / 2, mPaint);//畫文字 } /** * 設定當前進度 * * @param currentProgress */ public void setCurrentProgress(int currentProgress) { if (currentProgress <= 0) { currentProgress = 0; if (listener != null) { listener.startLoad(); } } if (currentProgress >= maxProgress) { currentProgress = maxProgress; if (listener != null) { listener.loadEnd(); } } this.currentProgress = currentProgress; if (listener != null) { listener.progressLoading(currentProgress); } invalidate();//重繪 } public void setListener(ProgressedListener listener) { this.listener = listener; } public interface ProgressedListener { void loadEnd();//載入結束 void progressLoading(int progressed);//載入中 void startLoad();//開始載入 } }
  • 自定義屬性 attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CircleProgressView">
        <!-- 背景色-->
        <attr name="circleprogress_backgroundcolor" format="color" />
        <!-- 前景色-->
        <attr name="circleprogress_foregroundcolor" format="color" />
        <!-- 進度條顏色 -->
        <attr name="circleprogress_progresscolor" format="color" />
        <!-- 字型顏色-->
        <attr name="circleprogress_fontcolor" format="color" />
        <!-- 最大進度 -->
        <attr name="circleprogress_maxprogress" format="integer" />
        <!-- 進度寬 -->
        <attr name="circleprogress_width" format="integer" />
        <!-- 字型大小-->
        <attr name="circleprogress_textsize" format="integer" />

    </declare-styleable>
</resources>
  • 佈局檔案 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:circleprogress="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:background="#ffffff"
    android:orientation="vertical"
    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="com.wxq.me.mycsdndemo.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <com.wxq.me.mycsdndemo.CircleProgressView
            android:id="@+id/circle_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            circleprogress:circleprogress_backgroundcolor="#dddddd"
            circleprogress:circleprogress_fontcolor="#0000ff"
            circleprogress:circleprogress_foregroundcolor="#ffffff"
            circleprogress:circleprogress_maxprogress="100"
            circleprogress:circleprogress_progresscolor="#0000ff" />

        <com.wxq.me.mycsdndemo.CircleProgressView
            android:id="@+id/circle_view1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            circleprogress:circleprogress_backgroundcolor="#000000"
            circleprogress:circleprogress_fontcolor="#ff0000"
            circleprogress:circleprogress_foregroundcolor="#ffffff"
            circleprogress:circleprogress_maxprogress="100"
            circleprogress:circleprogress_progresscolor="#ff0000"
            circleprogress:circleprogress_textsize="20"
            circleprogress:circleprogress_width="5" />

        <com.wxq.me.mycsdndemo.CircleProgressView
            android:id="@+id/circle_view2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            circleprogress:circleprogress_backgroundcolor="#ff0000"
            circleprogress:circleprogress_fontcolor="#ffff00"
            circleprogress:circleprogress_foregroundcolor="#ffffff"
            circleprogress:circleprogress_maxprogress="100"
            circleprogress:circleprogress_progresscolor="#ffff00"
            circleprogress:circleprogress_textsize="20"
            circleprogress:circleprogress_width="5" />
    </LinearLayout>

    <com.wxq.me.mycsdndemo.CircleProgressView
        android:id="@+id/circle_view3"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        circleprogress:circleprogress_backgroundcolor="#dddddd"
        circleprogress:circleprogress_fontcolor="#00ffff"
        circleprogress:circleprogress_foregroundcolor="#ffffff"
        circleprogress:circleprogress_maxprogress="100"
        circleprogress:circleprogress_progresscolor="#00ffff"
        circleprogress:circleprogress_textsize="50"
        circleprogress:circleprogress_width="20" />
</LinearLayout>
  • MainActivity.java
public class MainActivity extends AppCompatActivity {

    private CircleProgressView mCircleProgressView, mCircleProgressView1, mCircleProgressView2, mCircleProgressView3;

    private int currentProgress = 0;

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if (currentProgress <= 100) {
                mCircleProgressView.setCurrentProgress(currentProgress);
                mCircleProgressView1.setCurrentProgress(currentProgress);
                mCircleProgressView2.setCurrentProgress(currentProgress);
                mCircleProgressView3.setCurrentProgress(currentProgress);
                Log.i("wx", currentProgress + "");
                currentProgress++;
                sendEmptyMessageDelayed(1, 10);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mCircleProgressView = (CircleProgressView) findViewById(R.id.circle_view);
        mCircleProgressView1 = (CircleProgressView) findViewById(R.id.circle_view1);
        mCircleProgressView2 = (CircleProgressView) findViewById(R.id.circle_view2);
        mCircleProgressView3 = (CircleProgressView) findViewById(R.id.circle_view3);
        mCircleProgressView.setListener(new CircleProgressView.ProgressedListener() {
            @Override
            public void loadEnd() {
                Toast.makeText(MainActivity.this, "載入結束", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void progressLoading(int progressed) {
                //TODO
            }

            @Override
            public void startLoad() {
                Toast.makeText(MainActivity.this, "載入開始", Toast.LENGTH_SHORT).show();
            }
        });
        mHandler.sendEmptyMessageDelayed(1, 1000);
    }
}
  • 實現思路

    1. 在onDraw方法中先中繪製外圓,再去繪製扇形,再繪製內圓,最後繪製文字。
    2. 在CircleProgressView定義介面ProgressedListener,MainActivity中實現這個介面,開始載入回撥startLoad方法,載入中回撥progressLoading方法,載入結束回撥loadEnd方法。
    3. 在MainActivity使用handler模擬進度載入呼叫setCurrentProgress方法。