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.运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中可以通过自定义View来实现圆弧进度条。以下是实现步骤: 1. 创建一个自定义View类,并继承View。在构造方法中初始化画笔和属性。 2. 重写onMeasure方法,指定View的宽高。 3. 重写onDraw方法,通过Canvas绘制圆弧。 4. 添加一个方法用于设置进度条的进度值,例如setProgress(int progress)。 5. 在onDraw方法中使用Path和Canvas绘制圆弧。 6. 在setProgress方法中计算当前进度对应的角度,然后调用invalidate方法强制刷新视图。 7. 使用属性动画或ObjectAnimator来实现进度条动画效果。 8. 在布局文件中添加自定义View并设置相关属性。 9. 在Java代码中调用setProgress方法来更新进度条的值。 以下是一个简单的示例代码: ``` public class CustomArcProgressBar extends View { private Paint paint; private RectF rectF; private int progress; public CustomArcProgressBar(Context context) { super(context); init(); } public CustomArcProgressBar(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CustomArcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { paint = new Paint(); rectF = new RectF(); progress = 0; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(Math.min(width, height), Math.min(width, height)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int centerX = getWidth() / 2; int centerY = getHeight() / 2; int radius = centerX - 10; paint.setColor(Color.GRAY); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE); rectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius); canvas.drawArc(rectF, 0, 360, false, paint); paint.setColor(Color.BLUE); canvas.drawArc(rectF, -90, (float) (progress * 3.6), false, paint); } public void setProgress(int progress) { if(progress >= 0 && progress <= 100) { this.progress = progress; invalidate(); } } } ``` 希望以上回答对您有帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值