自定义弧形进度条

  先上效果图:

  自定义View绘制进度条:

package com.example.test;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.Cap;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;


public class MyCircle extends View
{
    private static int DIAMETER = 0x5D; //Diameter英文为直径,该常量表示小圆直径的dp值
    private static int STROKE_WIDTH = 0x1B; // 该常量表示圆环宽度2倍的dp值
    
    private Paint mPaint;
    private int mProgress;// 表示进度
    private RectF mRect;
    private int mDiameter; // Diameter英文为直径,在该View中要绘制圆环,圆环由两个圆形确定(大圆和小圆),这个整形值表示小圆直径。
    private int mWidth;// 这个值表示圆环的宽度的2倍(大圆直径-小圆直径)
    
    private final int defaultColor; //进度条背景颜色
    private final int processColor; //进度条进度颜色
    
    public MyCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        int id = attrs.getAttributeResourceValue(
                "http://schemas.android.com/apk/res/android", "color", R.color.defaultColor);
        defaultColor = getResources().getColor(id);
        id = attrs.getAttributeResourceValue(
                "http://schemas.android.com/apk/res/android", "color", R.color.processColor);
        processColor = getResources().getColor(id);
        init();
    }
    
    private void init() {
        Resources res = getResources();
        //getDisplayMetrics()返回当前展示的metrics.
        DisplayMetrics metrics = res.getDisplayMetrics();
        //TypedValue.applyDimension(int unit, float value, DisplayMetrics metrics)
        //该方法中unit表示要转换成的单位,value表示数值,metrics表示当前的度量方式
        //DIAMETER是常量0x1E,十进制为30,下面语句就表示tmp的值为30dp换算成的像素数值
        float tmp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                DIAMETER, metrics);
        //ceil函数表示向上取整
        mDiameter = (int) Math.ceil(tmp);
        tmp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                STROKE_WIDTH, metrics);
        mWidth = (int) Math.ceil(tmp);
        
        Paint p = new Paint();
        //Paint.Style.STROKE表示空心,Paint.Style.FILL表示实心,Paint.Style.FILL_AND_STROKE表示空心与实心
        p.setStyle(Paint.Style.STROKE);
        p.setAntiAlias(true);
        //setStrokeWidth()设置画笔宽度
//        p.setStrokeWidth(0.5F*mWidth+0.5F*mDiameter);
        p.setStrokeWidth(0.5F*mWidth);
        p.setStrokeCap(Cap.ROUND);
        p.setColor(defaultColor);
        mPaint = p;
        
        float rightTop = (float) (mWidth / 2.0);//这个值就是圆环宽度(大圆半径-小圆半径)
        mRect = new RectF(rightTop, rightTop, mDiameter+rightTop, mDiameter+rightTop);
        mProgress = 0;
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        // super.onDraw(canvas);
        Paint paint = mPaint;
        //如果mProgress<360,则圆形进度条还未旋转完成,则用0x7f的透明度绘制一个完整的圆形作为进度条背景
        //注意要先绘制背景条,再绘制进度条,因为后绘制的会覆盖在先绘制的上面
        if (mProgress < 360) {
            paint.setAlpha(0x7f);
            paint.setColor(defaultColor);
            canvas.drawArc(mRect, 135, 270, false, paint);
        }
        if (mProgress != 0) {
            float degree = (float) (270.0f * mProgress / 360);
            paint.setAlpha(0xff);
            paint.setColor(processColor);
            //drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
            //该方法参数:
            //oval表示绘制椭圆的矩形边界;
            //startAngle表示起始角度;
            //useCenter
            //paint表示要使用的画笔;
            canvas.drawArc(mRect, 135, degree, false, paint);
        }
    }
    
    @Override
    protected final void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //mDiameter表示小圆直径,mWidth表示圆环宽度的2倍,所以meas表示大圆直径
        //所以View的hight,width都为meas
        final int meas = mDiameter + mWidth;
        setMeasuredDimension(meas, meas);
    }
    
    public void setProgress(int p) {
        mProgress = p;
        invalidate();
    }
    
    public void postProgress(final int p) {
        post(new Runnable(){
            @Override
            public void run() {
                setProgress(p);
            }
        });
    }
}

  布局文件太简单,不给了,activity也很简单:

public class MainActivity extends Activity {

    ViewPager devPager,roomPager,devItemPager;
    MyCircle myCircle;
    int mProgress = 1;
    
    @SuppressLint("HandlerLeak")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search_device_new_diaolog);
        myCircle = (MyCircle)findViewById(R.id.search_device_new_customcircle);
        final Handler handler = new Handler(){

            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                if(msg.what == 0x1223) {
                    myCircle.setProgress(mProgress);
                }
            }
        };
        
        new Timer().schedule(new TimerTask() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                Message msg = new Message();
                msg.what = 0x1223;
                if(mProgress < 360)
                {
                    mProgress++;
                }
                else {
                    this.cancel();
                }
                handler.sendMessage(msg);
            }
        }, 0, 500);
    }
}
原文地址:https://www.cnblogs.com/Couch-potato/p/3685633.html