Android 自定义圆弧计数器(模仿QQ计步器)

1.自定义属性

   在res的values文件夹中新建一个attrs.xml文件,如下图所示:

  

  在attrs.xml文件中自定义我们需要的view属性,定义内容如下所示:

<declare-styleable name="QQStepView">
         <!--外围圆弧的颜色-->
        <attr name="outerColor" format="color"/>
         <!--内围圆弧的颜色-->
        <attr name="interColor" format="color"/>
         <!--显示数字的文字大小-->
        <attr name="stepTextSize" format="dimension"/>
         <!--显示数据的颜色-->
        <attr name="stepTextColor" format="color"/>
         <!--圆弧的边框-->
        <attr name="borderWidth" format="dimension"/>
         <!--最大的数值-->
        <attr name="maxStep" format="integer"/>
         <!--当前的数值-->
        <attr name="currentStep" format="integer"/>
</declare-styleable>

2.自定义QQStepView 类继承至View类

  stepview代码如下所示:

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 mOuterColor = Color.BLUE;//默认外圆弧的颜色
    private int mInterColor = Color.RED;//默认内圆弧的颜色
    private int mTextStepColor = Color.RED;//默认显示数据的颜色
    private float mBorderWidth = 21;//默认圆弧的宽度
    private int mMaxStepValue = 5000;//默认最大的显示数据
    private int mCurrentStepValue = 1000;//默认当前的显示数据
    private Paint mOuterPaint;//外圆弧的画笔
    private Paint mInterPaint;//内圆弧的画笔
    private Paint mTextPaint;//数据的画笔
    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);
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.QQStepView);//从attrs.xml文件中获取自定义属性
        mOuterColor = typedArray.getColor(R.styleable.QQStepView_outerColor,mOuterColor);//获取外圆弧的颜色
        mInterColor = typedArray.getColor(R.styleable.QQStepView_interColor,mInterColor);//获取内圆弧的颜色
        mTextStepColor = typedArray.getColor(R.styleable.QQStepView_stepTextColor,mTextStepColor);//获取显示数据字体的颜色
        mBorderWidth = typedArray.getDimension(R.styleable.QQStepView_borderWidth,mBorderWidth);//获取圆弧的宽度
        mMaxStepValue = typedArray.getInteger(R.styleable.QQStepView_maxStep,mMaxStepValue);//获取最大的显示数据
        mCurrentStepValue = typedArray.getInteger(R.styleable.QQStepView_currentStep,mCurrentStepValue);//获取当前的显示数据
        typedArray.recycle();//资源文件的回收
        
        /**定义外圆弧的画笔样式*/
        mOuterPaint = new Paint();
        mOuterPaint.setAntiAlias(true);
        mOuterPaint.setColor(mOuterColor);
        mOuterPaint.setStrokeWidth(mBorderWidth);
        mOuterPaint.setStrokeCap(Paint.Cap.ROUND);
        mOuterPaint.setStyle(Paint.Style.STROKE);

        /**定义内圆弧的画笔样式*/
        mInterPaint = new Paint();
        mInterPaint.setAntiAlias(true);
        mInterPaint.setColor(mInterColor);
        mInterPaint.setStrokeWidth(mBorderWidth);
        mInterPaint.setStrokeCap(Paint.Cap.ROUND);
        mInterPaint.setStyle(Paint.Style.STROKE);

        /**定义显示字体的画笔样式*/
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(mTextStepColor);
        mTextPaint.setTextSize(60);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);//获取长度
        int height = MeasureSpec.getSize(heightMeasureSpec);//获取宽度
        setMeasuredDimension(width>height?height:width,width>height?height:width);//确保是个正方形
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int center = getWidth()/2;
        int radis = (int) (center - mBorderWidth/2);
        //外侧的圆弧
        RectF outRect = new RectF(center-radis,center-radis,center+radis,center+radis);
        canvas.drawArc(outRect,135,270,false,mOuterPaint);
        //内侧的圆弧
        float sweepAngle = 0;
        if(mCurrentStepValue>0)
            sweepAngle= (float) mCurrentStepValue/(float)mMaxStepValue*270;
        canvas.drawArc(outRect,135,sweepAngle,false,mInterPaint);
        //绘画文字
        Rect textRect = new Rect();
        mTextPaint.getTextBounds(mCurrentStepValue+"",0,String.valueOf(mCurrentStepValue).length(),textRect);
        int dx = getWidth()/2 - textRect.width()/2;
        int dy = (textRect.bottom-textRect.top)/2 - textRect.top;
        int baseLine = (int) (getHeight()/2 +dy-mBorderWidth);

        canvas.drawText(mCurrentStepValue+"",dx,baseLine,mTextPaint);
    }

    public void setmMaxStepValue(int maxStepValue){
        this.mMaxStepValue = maxStepValue;
    }
    public void setmCurrentStepValue(int currentStepValue){
        this.mCurrentStepValue = currentStepValue;
        invalidate();
    }
}

3.在布局文件中的使用

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <com.hong.myview.QQStepView
        android:id="@+id/qq_step_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

4.代码中的使用

import androidx.appcompat.app.AppCompatActivity;

import android.animation.ValueAnimator;
import android.os.Bundle;
import android.view.animation.DecelerateInterpolator;

public class MainActivity extends AppCompatActivity {
    private QQStepView qqStepView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        qqStepView = this.findViewById(R.id.qq_step_view);
        qqStepView.setmMaxStepValue(3000);
        //添加动画
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0,2500);//0-2500数字
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(1500);//1.5s的动画效果
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
               int currentStep = (int) animation.getAnimatedValue();//获取当前的动画值,即(0-2500的数字)
                qqStepView.setmCurrentStepValue(currentStep);//重新绘制view
            }
        });
        valueAnimator.start();//开启动画
    }
}

5.运行结果

猜你喜欢

转载自blog.csdn.net/h5630/article/details/113867269