自定义圆形百分比view

作者: 辉辉_ | 来源:发表于2017-03-22 15:48 被阅读154次
    device-2017-03-22-153115.png

    圆形百分比view主要是对canvas的操作以及坐标的计算

    /**
     * Description:
     * - - - - - - - - - - - - - - - - - - -
     * Created by HUI on 17/3/20.
     * - - - - - - - - - - - - - - - - - - -
     * Version 1.0.0
     */
    
    public class CircleProgressView extends View {
        private static final int CIRCLE_RADIUS = 360;
        private static final int MAX_RADIUS = 300;    //外圆半径
        private static final int MIN_RADIUS = 280;    //内圆半径
        private static final float SCALE_SPACE = 3.6f;//刻度之间的间隔-->每3.6度画一格
    
        private int mWidth; //view宽
        private int mHeight;//View高
        private int centerX;    //view中心点 x
        private int centerY;    //view中心点 y
        private int mProgress = -1;  //当前进度
        private Paint circlePaint;//画圆画笔
        private Paint textPaint;//文字画笔
        private int defaultProgressColor = Color.parseColor("#bfcabf"); //默认刻度线颜色
        private int doneProgressColor = Color.parseColor("#ae850d");    //已完成刻度线颜色
        private float progressStrokeWidth = 4.0f;   //刻度线宽
        private int textSize = 40;  //中心文字大小
        private int textColor = Color.parseColor("#000000");    //文字颜色
    
    
        public CircleProgressView(Context context) {
            super(context);
            init(context, null);
        }
    
        public CircleProgressView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context, attrs);
        }
    
        public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context, attrs);
        }
    
        private void init(Context context, AttributeSet attrs) {
            if (attrs != null) {
                //获取自定义属性
                TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView);
                defaultProgressColor = attributes.getColor(R.styleable.CircleProgressView_default_progress_color, Color.parseColor("#bfcabf"));
                doneProgressColor = attributes.getColor(R.styleable.CircleProgressView_done_progress_color, Color.parseColor("#ae850d"));
                progressStrokeWidth = attributes.getFloat(R.styleable.CircleProgressView_progress_stroke_width, 4.0f);
                textSize = attributes.getDimensionPixelSize(R.styleable.CircleProgressView_center_text_size, 40);
                textColor = attributes.getColor(R.styleable.CircleProgressView_center_text_color, Color.parseColor("#000000"));
                attributes.recycle();
            }
    
            //画圆画笔
            circlePaint = new Paint();
            circlePaint.setColor(defaultProgressColor);
            circlePaint.setAntiAlias(true);
            circlePaint.setStrokeWidth(progressStrokeWidth);
            circlePaint.setStyle(Paint.Style.FILL);
    
            //文字画笔
            textPaint = new Paint();
            textPaint.setColor(textColor);
            textPaint.setAntiAlias(true);
            textPaint.setTextSize(textSize);
            textPaint.setStyle(Paint.Style.FILL);
            textPaint.setTextAlign(Paint.Align.CENTER);
        }
    
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            mWidth = MeasureSpec.getSize(widthMeasureSpec);
            mHeight = MeasureSpec.getSize(heightMeasureSpec);
            centerX = mWidth / 2;
            centerY = mHeight / 2;
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
        @Override
        protected void onDraw(final Canvas canvas) {
            //①绘制一圈默认刻度
            circlePaint.setColor(defaultProgressColor);
            drawScale(canvas, CIRCLE_RADIUS, circlePaint);
    
            //②绘制文字
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            float top = fontMetrics.top;
            float bottom = fontMetrics.bottom;
            //重新计算出文字中心点的Y坐标
            int textY = (int) (mHeight / 2 - top / 2 - bottom / 2);
            //展示进度
            canvas.drawText(Math.max(mProgress, 0) + "%", centerX, textY, textPaint);
    
            //③绘制已完成的刻度
            circlePaint.setColor(doneProgressColor);
            drawScale(canvas, mProgress * SCALE_SPACE, circlePaint);
        }
    
        //绘制刻度线
        private void drawScale(Canvas canvas, float progress, Paint paint) {
            if (progress <= 0) {
                return;
            }
    
            float degree;   //弧度
            float startX, startY, endX, endY;
            for (float i = 1, j; (j = i * SCALE_SPACE) <= progress ; i++) {
                degree = (float) getRadian(j);
                //刻度线的长度就是大圆与小圆的半径差
                startX = centerX + (float) Math.sin(degree) * MIN_RADIUS;
                startY = centerY - (float) Math.cos(degree) * MIN_RADIUS;
                endX = centerX + (float) Math.sin(degree) * MAX_RADIUS;
                endY = centerY - (float) Math.cos(degree) * MAX_RADIUS;
                canvas.drawLine(startX, startY, endX, endY, paint);
            }
        }
    
    
        //设置当前已完成进度
        public synchronized void setCurrentProgress(final int progress) {
            if (progress < 0 || progress > 100) {
                throw new RuntimeException("当前进度不合法");
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i <= progress; i++) {
                        try {
                            Thread.sleep(15);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        mProgress = i;
                        postInvalidate();
                    }
    
                }
            }).start();
        }
    
        //转化角度
        private double getRadian(float i) {
            return i * Math.PI / 180;
        }
    }
    

    </br>
    在values文件夹下新建自定义属性文件attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="CircleProgressView">
            <!--默认刻度颜色-->
            <attr name="default_progress_color" format="color|reference"/>
            <!--已完成刻度颜色-->
            <attr name="done_progress_color" format="color|reference"/>
            <!--刻度线宽度-->
            <attr name="progress_stroke_width" format="float"/>
            <!--文字大小-->
            <attr name="center_text_size" format="dimension"/>
            <!--文字颜色-->
            <attr name="center_text_color" format="color|reference"/>
        </declare-styleable>
    </resources>
    

    </br>
    在布局中使用该自定义控件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  android:orientation="vertical"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
        <Button
            android:text="设置进度75"
            android:id="@+id/start"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        
        
        <com.summer.tree.widget.CircleProgressView
            android:id="@+id/cv"
            android:layout_marginTop="20dp"
            app:default_progress_color="#bfcabf"
            app:done_progress_color="#ae850d"
            app:center_text_size="20dp"
            app:progress_stroke_width="6.0"
            app:center_text_color="#0000ff"
            android:layout_width="match_parent"
            android:layout_height="320dp"/>
    
    </LinearLayout>
    

    在代码中调用setCurrentProgress()方法设置具体进度范围0-100

    效果图:


    circleprogress.gif

    相关文章

      网友评论

        本文标题:自定义圆形百分比view

        本文链接:https://www.haomeiwen.com/subject/mzmonttx.html