Android 自定义记录步数控件

本文介绍了如何使用Java实现一个自定义的圆形进度条QQStepView,包括设置颜色、边框宽度、字体大小等属性,并通过属性动画展示了平滑的进度变化效果。在MainActivity中,通过ValueAnimator设置了从0到指定最大值的动画,以动态更新进度条的状态。
摘要由CSDN通过智能技术生成

代码

package com.sd.myimageview;

import android.annotation.SuppressLint;
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;

public class QQStepView extends View {
    private int mStepOuterColor = Color.BLUE;
    private int mStepInnerColor = Color.YELLOW;
    //代表20px
    private int mStepBorderWidth = 30;
    private int mStepTextSize = 16;
    private int mStepTextColor = Color.BLACK;
    //外圆弧画笔
    private Paint mStepOuterPaint;
    //内圆弧画笔
    private Paint mStepInnerPaint;
    //文字画笔
    private Paint mStepTextPaint;
    //总进度
    private int mStepMax = 0;
    //当前进度
    private int mStepCurrent = 0;

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

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

    public QQStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    /**
     * 获取自定义属性
     */
    private void init(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.QQStepView);
        mStepInnerColor = array.getColor(R.styleable.QQStepView_step_innerColor, mStepInnerColor);
        mStepOuterColor = array.getColor(R.styleable.QQStepView_step_outerColor, mStepOuterColor);
        mStepBorderWidth = (int) array.getDimension(R.styleable.QQStepView_step_borderWidth, mStepBorderWidth);
        mStepTextSize = array.getDimensionPixelSize(R.styleable.QQStepView_step_TextSize, mStepTextSize);
        mStepTextColor = array.getColor(R.styleable.QQStepView_step_TextColor, mStepTextColor);
        array.recycle();
        // TODO: 2020/11/30 初始化外弧度画笔
        mStepOuterPaint = new Paint();
        mStepOuterPaint.setAntiAlias(true);
        mStepOuterPaint.setStrokeWidth(mStepBorderWidth);
        mStepOuterPaint.setColor(mStepOuterColor);
        mStepOuterPaint.setStyle(Paint.Style.STROKE);
        mStepOuterPaint.setStrokeCap(Paint.Cap.ROUND);
        // TODO: 2020/11/30 初始化内弧度画笔
        mStepInnerPaint = new Paint();
        mStepInnerPaint.setAntiAlias(true);
        mStepInnerPaint.setStrokeWidth(mStepBorderWidth);
        mStepInnerPaint.setColor(mStepInnerColor);
        mStepInnerPaint.setStyle(Paint.Style.STROKE);
        mStepInnerPaint.setStrokeCap(Paint.Cap.ROUND);
        // TODO: 2020/11/30 文字画笔
        mStepTextPaint = new Paint();
        mStepTextPaint.setColor(mStepTextColor);
        mStepTextPaint.setAntiAlias(true);
        mStepTextPaint.setTextSize(mStepTextSize);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(Math.min(width, height), Math.min(height, width));
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        RectF rectF = new RectF(mStepBorderWidth / 2, mStepBorderWidth / 2, getWidth() - mStepBorderWidth / 2, getWidth() - mStepBorderWidth / 2);
        // TODO: 2020/11/30 内弧度
        canvas.drawArc(rectF, 135, 270, false, mStepOuterPaint);
        if (mStepMax == 0) return;
        // TODO: 2020/11/30 得出当前的步数占总步数的百分比,然后乘以270  这个强制转换应该是要加,不然会没效果的
        float sweepAngle = (float) mStepCurrent / mStepMax;
        // TODO: 2020/11/30 外弧度
        canvas.drawArc(rectF, 135, sweepAngle * 270, false, mStepInnerPaint);
        // TODO: 2020/11/30 绘制文字
        String stepText = mStepCurrent + "";
        Rect bounds = new Rect();
        mStepTextPaint.getTextBounds(stepText, 0, stepText.length(), bounds);
        // TODO: 2020/11/30 文字横坐标为控件宽度的一半减去文字宽度的一半
        int dx = getWidth() / 2 - bounds.width() / 2;
        Paint.FontMetricsInt fontMetricsInt = mStepTextPaint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
        // TODO: 2020/11/30 文字纵坐标为文字基线加上文字高度的一半
        int baseLine = getHeight() / 2 + dy;
        canvas.drawText(stepText, dx, baseLine, mStepTextPaint);
    }

    public synchronized void setStepMax(int max){
        this.mStepMax = max;
    }

    public synchronized void setStepCurrent(int current){
        this.mStepCurrent = current;
        //不断绘制
        invalidate();
    }
}

MainActivity调用

        qqStepView.setStepMax(4000);
        //属性动画
        // TODO: 2020/11/30 这个是表示零到三千慢慢的累加 
        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 3000);
        // TODO: 2020/11/30 一秒内加载完 
        valueAnimator.setDuration(1000);
        // TODO: 2020/11/30 前面速度比较快,后面比较慢 
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animatedValue = (float) animation.getAnimatedValue();
                qqStepView.setStepCurrent((int) animatedValue);
            }
        });
        valueAnimator.start();

效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值