统计步数,额度的圆弧自定义View

在这里插入图片描述
发现很多应用中都有类似于这种的自定义控件,自己撸了一个控件。

1.先自定义属性来控制圆弧的带下和颜色以及中间颜色和字体大小等
在res目录下的values文件夹中创建attrs.xml文件。

<?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.在自定义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.测量控件大小,一般这种控件都是正方形的。

 //测量大小
    @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.绘制:
4.1绘制外圈圆弧。

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绘制内圈圆弧。

   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绘制中间文字。

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.使用动画使文字和圆弧运动起来。

 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();
    }

以下就是全部代码:

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();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值