Count the number of steps and the amount of arc custom View

Insert picture description here
I found that there are custom controls similar to this in many applications, and I chose a control myself.

1. First customize the attributes to control the band and color of the arc, the middle color and font size, etc.
Create attrs.xml file in the values ​​folder under the res directory.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ArcStatisticsView">
        <attr name="OuterLayerColor" format="color" />
        <attr name="InnerLayerColor" format="color" />
        <attr name="ArcSize" format="dimension" />
        <attr name="StatisticsTextSize" format="dimension" />
        <attr name="StatisticsTextColor" format="color" />
    </declare-styleable>
</resources>

2. Get attributes in the custom View:

//获取自定义的属性值
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ArcStatisticsView);
        OuterLayerColor = typedArray.getColor(R.styleable.ArcStatisticsView_OuterLayerColor, Color.RED);
        InnerLayerColor = typedArray.getColor(R.styleable.ArcStatisticsView_InnerLayerColor, Color.GREEN);
        ArcSize = (int) typedArray.getDimension(R.styleable.ArcStatisticsView_ArcSize, ArcSize);
        StatisticsTextSize = (int) typedArray.getDimension(R.styleable.ArcStatisticsView_StatisticsTextSize, StatisticsTextSize);
        StatisticsTextColor = typedArray.getColor(R.styleable.ArcStatisticsView_StatisticsTextColor, Color.GREEN);
        typedArray.recycle();

3. Measure the size of the control, generally this kind of control is square.

 //测量大小
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取设置的宽和高
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        //哪个值小就用哪个值正方形
        setMeasuredDimension(widthSize > heightSize ? heightSize : widthSize, widthSize > heightSize ? heightSize : widthSize);
    }

4. Drawing:
4.1 Draw the outer circle arc.

private void drawOuterLayer(Canvas canvas) {
    //设置画笔的属性
    paint.setAntiAlias(true);
    //设置画笔颜色
    paint.setColor(OuterLayerColor);
    //设置画笔大小
    paint.setStrokeWidth(ArcSize);
    //设置画笔模式(描边模式)
    paint.setStyle(Paint.Style.STROKE);
    //设置为圆头(如果不设置的话就会是直角边)
    paint.setStrokeCap(Paint.Cap.ROUND);
    //第四个参数控制是否和圆心连接起来
    //创建一个矩阵 圆弧绘制在矩阵中(因为绘制的线条有宽度所以需要减去不然会出现显示不全)
    rect = new RectF(ArcSize / 2, ArcSize / 2, getWidth() - ArcSize / 2, getHeight());
    canvas.drawArc(rect, 135, 270, false, paint);
}

4.2 Draw the inner circle arc.

   private void drawInnerLayer(Canvas canvas) {
        paint.setColor(InnerLayerColor);
        //防止初始化还未设置MaxValue时 出现除以0导致奔溃
        if (MaxValue == 0)
            return;
        canvas.drawArc(rect, 135, (float) processValue / MaxValue * 270, false, paint);
    }

4.3 Draw the middle text.

private void drawCentreText(Canvas canvas) {
    //改回填充模式
    paint.setStyle(Paint.Style.FILL);
    //设置文字颜色
    paint.setColor(StatisticsTextColor);
    //设置文字大小
    paint.setTextSize(StatisticsTextSize);
    Rect bounds = new Rect();
    //测量文字的宽高
    paint.getTextBounds((processValue + ""), 0, (processValue + "").length(), bounds);
    canvas.drawText(processValue + "", ((float) (getWidth() - bounds.width()) / 2), getHeight() / 2+bounds.height()/2, paint);
}

5. Use animation to move text and arcs.

 asv = findViewById(R.id.asv);
        asv.setMaxValue(5000);
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 4800);
        valueAnimator.setDuration(2000);
        valueAnimator.setInterpolator(new LinearOutSlowInInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animatedValue = (float) animation.getAnimatedValue();
                asv.setProcessValue((int) animatedValue);
            }
        });
        valueAnimator.start();
    }

The following is the entire code:

package com.zg.viewdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * 圆弧统计的View
 */
public class ArcStatisticsView extends View {
    private RectF rect;
    /**
     * 外层颜色值
     */
    private int OuterLayerColor;
    /**
     * 内层颜色值
     */
    private int InnerLayerColor;
    /**
     * 圆弧大小
     */
    private int ArcSize;
    /**
     * 中间文字大小
     */
    private int StatisticsTextSize;
    /**
     * 中间文字颜色值
     */
    private int StatisticsTextColor;
    /**
     * 最大值
     */
    private int MaxValue;
    /**
     * 当前值
     */
    private int processValue;

    public void setMaxValue(int maxValue) {
        this.MaxValue = maxValue;
        invalidate();
    }

    public void setProcessValue(int processValue) {
        this.processValue = processValue;
        invalidate();
    }

    private Paint paint = new Paint();

    public ArcStatisticsView(Context context) {
        this(context, null);
    }

    public ArcStatisticsView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ArcStatisticsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取自定义的属性值
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ArcStatisticsView);
        OuterLayerColor = typedArray.getColor(R.styleable.ArcStatisticsView_OuterLayerColor, Color.RED);
        InnerLayerColor = typedArray.getColor(R.styleable.ArcStatisticsView_InnerLayerColor, Color.GREEN);
        ArcSize = (int) typedArray.getDimension(R.styleable.ArcStatisticsView_ArcSize, ArcSize);
        StatisticsTextSize = (int) typedArray.getDimension(R.styleable.ArcStatisticsView_StatisticsTextSize, StatisticsTextSize);
        StatisticsTextColor = typedArray.getColor(R.styleable.ArcStatisticsView_StatisticsTextColor, Color.GREEN);
        typedArray.recycle();
    }

    //测量大小
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取设置的宽和高
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        //哪个值小就用哪个值正方形
        setMeasuredDimension(widthSize > heightSize ? heightSize : widthSize, widthSize > heightSize ? heightSize : widthSize);
    }

    //绘制
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 1.绘制外层圆弧
        drawOuterLayer(canvas);
        //2.绘制内层圆弧
        drawInnerLayer(canvas);
        //3.绘制中间部分文字
        drawCentreText(canvas);
    }

    private void drawCentreText(Canvas canvas) {
        //改回填充模式
        paint.setStyle(Paint.Style.FILL);
        //设置文字颜色
        paint.setColor(StatisticsTextColor);
        //设置文字大小
        paint.setTextSize(StatisticsTextSize);
        Rect bounds = new Rect();
        //测量文字的宽高
        paint.getTextBounds((processValue + ""), 0, (processValue + "").length(), bounds);
        canvas.drawText(processValue + "", ((float) (getWidth() - bounds.width()) / 2), getHeight() / 2+bounds.height()/2, paint);
    }

    private void drawInnerLayer(Canvas canvas) {
        paint.setColor(InnerLayerColor);
        //防止初始化还未设置MaxValue时 出现除以0导致奔溃
        if (MaxValue == 0)
            return;
        canvas.drawArc(rect, 135, (float) processValue / MaxValue * 270, false, paint);
    }

    private void drawOuterLayer(Canvas canvas) {
        //设置画笔的属性
        paint.setAntiAlias(true);
        //设置画笔颜色
        paint.setColor(OuterLayerColor);
        //设置画笔大小
        paint.setStrokeWidth(ArcSize);
        //设置画笔模式(描边模式)
        paint.setStyle(Paint.Style.STROKE);
        //设置为圆头(如果不设置的话就会是直角边)
        paint.setStrokeCap(Paint.Cap.ROUND);
        //第四个参数控制是否和圆心连接起来
        //创建一个矩阵 圆弧绘制在矩阵中(因为绘制的线条有宽度所以需要减去不然会出现显示不全)
        rect = new RectF(ArcSize / 2, ArcSize / 2, getWidth() - ArcSize / 2, getHeight());
        canvas.drawArc(rect, 135, 270, false, paint);
    }
}
public class MainActivity extends AppCompatActivity {
    private ArcStatisticsView asv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        asv = findViewById(R.id.asv);
        asv.setMaxValue(5000);
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 4800);
        valueAnimator.setDuration(2000);
        valueAnimator.setInterpolator(new LinearOutSlowInInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animatedValue = (float) animation.getAnimatedValue();
                asv.setProcessValue((int) animatedValue);
            }
        });
        valueAnimator.start();
    }
}

Guess you like

Origin blog.csdn.net/qq77485042/article/details/109001113