Android 自定义圆形进度条

来源:互联网 发布:latex mac 编辑:程序博客网 时间:2024/06/03 12:34
import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import com.example.customedemo2.view.CircleProgressView;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);      CircleProgressView circleProgress = (CircleProgressView) findViewById(R.id.circleView);        //创建并开启线程        new Thread(circleProgress).start();    }}
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.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import android.widget.Switch;import com.example.customedemo2.R;/** * Created by 知足 on 2017/11/30. */public class CircleProgressView extends View implements  Runnable{    //内圆环半径    private int innerCircleReadius = 100;   //画内部实心圆的画笔    private Paint innerPaint;    //画外部实心圆的笔    private Paint outCircleRingPaint;    //默认的外部圆环宽度    private int outCircleWidth = 20;    //绘制文本内容的笔    private Paint mTextPain;    //圆的中心点    private int centerX;    private int centerY;    //圆环的半径    private int outRingRadius;    private RectF rectF;    //定义一个初始进度值    private int progress = 0;    //加载进度    private int totalProgress=100;    public CircleProgressView(Context context)    {        this(context,null);    }    public CircleProgressView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //关联我们所声明的自定义属性        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgressView, defStyleAttr, 0);        //获取属性        //获取内圆半径        innerCircleReadius= ta.getInt(R.styleable.CircleProgressView_innerCircleRadius, innerCircleReadius);      init();        //释放资源        ta.recycle();    }    /***     * 创建一个初始化画笔的方法     * 用于封装画笔相关设置     * */    private void  init(){        innerPaint = new Paint();        //设置画笔颜色        innerPaint.setColor(Color.parseColor("#d5982e"));        //设置抗拒齿        innerPaint.setAntiAlias(true);        //创建画外部圆环的画笔        outCircleRingPaint = new Paint();        outCircleRingPaint.setColor(Color.parseColor("#2a982e"));        //设置是否填充圆        outCircleRingPaint.setStyle(Paint.Style.STROKE);        //设置描述宽度(圆环宽度)        outCircleRingPaint.setStrokeWidth(outCircleWidth);        outCircleRingPaint.setAntiAlias(true);        //设置这个角        outCircleRingPaint.setStrokeCap(Paint.Cap.ROUND);        //创建文字画笔        mTextPain = new Paint();        //设置大小        mTextPain.setTextSize(50);    }    @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);        //定义变量记录控件的宽高        int width=0;        int height=0;        switch (widthMode){            case  MeasureSpec.UNSPECIFIED :                {                //很少用               }               break;            case MeasureSpec.AT_MOST ://wrap_content            {                width=innerCircleReadius * 2 +outCircleWidth * 2;            }            break;            case MeasureSpec.EXACTLY://match_parent            {                width=widthSize;            }            break;        }        switch(heightMode){            case  MeasureSpec.UNSPECIFIED :            {                //很少用            }            break;            case MeasureSpec.AT_MOST ://wrap_content            {                //精准模式                height=innerCircleReadius * 2 + outCircleWidth * 2;            }            break;            case MeasureSpec.EXACTLY : //math_parent            {                height=heightSize;//至多有多大            }            break;        }        //必须调用 ,如果不调用的话,测量的这个高度会出现偏差        setMeasuredDimension(width,height);    }    //得到测量后的控件的真实宽高    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        //得到圆中点        centerX= w/2;        centerY= h/2;        //圆环的半径        outRingRadius= w / 2 -outCircleWidth;        //确定圆环的绘制区域        rectF=new RectF();        rectF.left=centerX - outRingRadius;        rectF.top=centerY - outRingRadius;        rectF.right = centerX +outRingRadius;        rectF.bottom = centerY +outRingRadius;    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);    }    /**     * 这是一个绘制图形界面的方法     * @param canvas 画布     */    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);      drawInnerCircle(canvas);      drawOutCircleRing(canvas);      dreawText(canvas);    }    /**     * 绘制文本     * @param canvas     */    private  void  dreawText(Canvas canvas){        String des= progress + "%";        //得到文字的宽度与高度        Paint.FontMetrics fm=new Paint.FontMetrics();        //得到文字的高度        int tetHeight =(int) Math.ceil(fm.descent - fm.ascent);        //得到文字的宽度        int textWidth = (int) mTextPain.measureText(des, 0, des.length());        canvas.drawText(des,getWidth()/2-(textWidth /2),getHeight()/2 -(tetHeight/2),mTextPain);    }    /**     * 画内部实心圆     * @param canvas     */    private void  drawInnerCircle(Canvas canvas){        canvas.drawCircle(getWidth()/2,getHeight()/2,innerCircleReadius,innerPaint);    }    /**     * 画外圆环     * @param canvas     */    private void  drawOutCircleRing(Canvas canvas){        // 1 / 100 = 0 2 / 100 =  100%  1 *   1 2  3  4  5        //canvas.drawArc(getWidth() / 2 -        // innerCircleRadius,getHeight() /        // 2 - innerCircleRadius,getWidth() / 2 +        // innerCircleRadius,getHeight() / 2 +        // innerCircleRadius,-90,(progress * 360) /        // totalProgress,false,outCircleRingPaint);        canvas.drawArc(rectF,-90,(progress * 360)/ totalProgress,false,outCircleRingPaint);    }    @Override    public void run() {        while (true){            if(progress<100){                progress++;                try {                    Thread.sleep(100);                } catch (InterruptedException e) {                    e.printStackTrace();                }                postInvalidate();            }else{                progress=0;            }        }    }}



<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:test="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.example.customedemo2.MainActivity">    <com.example.customedemo2.view.CircleProgressView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/circleView"        test:innerCircleRadius="300"        /></LinearLayout>





attrs
<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="CircleProgressView">        <attr name="innerCircleRadius" format="integer"/>    </declare-styleable></resources>