自定義View-仿QQ運動步數(shù)進度效果(完整代碼)

解析請看這自定義View-仿QQ運動步數(shù)進度效果

一、attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="centerTextSize" format="dimension"/>
    <!-- 外圍圓弧大小-->
    <attr name="cirleSize" format="dimension"/>
    <!-- 步婁文字顏色大小-->
    <attr name="centerTextColor" format="color"/>
    <!-- 外圍圓弧顏色-->
    <attr name="cirleForeginColor" format="color"/>
    <!-- 內圍圓弧顏色-->
    <attr name="centerInnerColor" format="color"/>
</declare-styleable>

</resources>

二、ProgressRunView

package com.example.myapplication.Widget;

import android.animation.ValueAnimator;
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.util.Log;
import android.util.TypedValue;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.myapplication.R;


public class ProgressRunView extends View {

    /**
     * 畫筆的設置
     */
    private Paint paintText;
    private Paint paintCirle;
    private Paint paintCirleInner;

    private int centerTextSize = 20;
    private float cirleSize = 1;
    private int centerTextColor = Color.BLUE;
    private int cirleForeginColor = Color.BLUE;
    private int centerInnerColor = Color.RED;
    private Context context;

    /**
     * 屬性獲取
     */
    private int x;
    private int y;

    public ProgressRunView(Context context) {
        super(context);
    }

    public ProgressRunView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ProgressRunView);
        centerTextSize = typedArray.getDimensionPixelSize(R.styleable.ProgressRunView_centerTextSize,Px2Sp(context,centerTextSize));
        cirleSize = typedArray.getDimension(R.styleable.ProgressRunView_cirleSize,cirleSize);
        centerTextColor = typedArray.getColor(R.styleable.ProgressRunView_centerTextColor,centerTextColor);
        cirleForeginColor = typedArray.getColor(R.styleable.ProgressRunView_cirleForeginColor,cirleForeginColor);
        centerInnerColor = typedArray.getColor(R.styleable.ProgressRunView_centerInnerColor,centerInnerColor);
        typedArray.recycle();


        paintText = new Paint();
        paintText.setColor(centerTextColor);
        paintText.setTextSize(centerTextSize);
        paintText.setAntiAlias(true);
        paintText.setDither(true);



        paintCirle = new Paint();
        paintCirle.setColor(cirleForeginColor);
        //設置畫筆的寬
        paintCirle.setStrokeWidth(20);
        paintCirle.setStrokeCap(Paint.Cap.ROUND);
        paintCirle.setStrokeJoin(Paint.Join.ROUND);
        paintCirle.setStyle(Paint.Style.STROKE);
        paintCirle.setAntiAlias(true);
        paintCirle.setDither(true);


        paintCirleInner = new Paint();
        paintCirleInner.setColor(centerInnerColor);
        //設置畫筆的寬
        paintCirleInner.setStrokeWidth(18);
        paintCirleInner.setStrokeCap(Paint.Cap.ROUND);
        paintCirleInner.setStrokeJoin(Paint.Join.ROUND);
        paintCirleInner.setStyle(Paint.Style.STROKE);
        paintCirleInner.setAntiAlias(true);
        paintCirleInner.setDither(true);



    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //獲取寬高的模式
         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
         //指定寬高的大小
         int width = MeasureSpec.getSize(widthMeasureSpec);
         int height = MeasureSpec.getSize(heightMeasureSpec);
         //如果寬高設置為wrap_content時,剛默認為500
         if(widthMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.AT_MOST){
             width = 500;
             height = width;
         }
        //如果寬高不一致時,則以寬為標準
         if(width != height){
             height = width;
         }

         setMeasuredDimension(width,height);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        drawText(canvas);
        drawCirle(canvas);
        drawCirleInner(canvas);
    }
    /**
     * 繪制內弧
     * @param canvas
     */
    private void drawCirleInner(Canvas canvas) {
        int radius = 200;
        RectF rectF = new RectF(x-radius,y-radius,x + radius,y+ radius);
        float sweepAngle = (float) Integer.valueOf(runText)/maxStep;
        //動態(tài)設置掃過的面積(弧的動態(tài)效果)
        canvas.drawArc(rectF, 135, sweepAngle*270, false, paintCirleInner);
    }



    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        //獲取中心點
        x = (right - left)/2;
        y = (bottom - top)/2;
    }

    /**
     * 繪制外弧
     * @param canvas
     */
    private void drawCirle(Canvas canvas) {
        int radius = 200;
        RectF rectF = new RectF(x-radius,y-radius,x + radius,y+ radius);

        canvas.drawArc(rectF, 135, 270, false, paintCirle);
    }
    private String runText = "0";

    /**
     * 繪制中間的文本
     * @param canvas
     */
    private void drawText(Canvas canvas) {
        Rect rect = new Rect();
        paintText.getTextBounds(runText,0,runText.length(),rect);
        Paint.FontMetrics fontMetrics =paintText.getFontMetrics();

        int dx = getWidth()/2 - rect.width()/2;
        //基線
        float baseline = getHeight()/2 + (fontMetrics.top-fontMetrics.bottom)/2-fontMetrics.top;
        canvas.drawText(runText,dx,baseline,paintText);
    }

    /**
     * Sp轉Px
     * @param context
     * @param px
     * @return
     */
    public int Px2Sp(Context context, int px) {
        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,px,context.getResources().getDisplayMetrics());
    }

    /**
     * 步數(shù)的重新繪制
     * @param progress
     */
    public synchronized void setProgress(int progress) {
        this.runText = String.valueOf(progress);
        // 重新刷新繪制 -> onDraw()
        invalidate();
    }

    /**
     * 設置最大值
     * @param maxStep
     */
    public synchronized void setMaxStep(int maxStep) {
        this.maxStep = maxStep;
    }

    private  int maxStep;

    /**
     * 開始運行
     * @param start 開始的大小
     * @param end 結束的大小
     */
    public void start(int start,int end){
        ValueAnimator valueAnimator = ValueAnimator.ofInt(start,end);
        //開始到結束的時間
        valueAnimator.setDuration(3000);
        valueAnimator.start();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                int currentStep = (int) valueAnimator.getAnimatedValue();
                //設置當前的步數(shù)并重新繪制
                setProgress(currentStep);
                Log.e("onAnimationUpdate: ", String.valueOf(currentStep));
            }
        });
    }

}

三、Activity

package com.example.myapplication;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

import com.example.myapplication.InterfaceCalkable.ScrollCallBack;
import com.example.myapplication.Widget.ProgressRunView;
import com.example.myapplication.Widget.ProgressView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ProgressRunView progressRunView;
    private Button btn_run;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

    }

    private void initView() {
        progressRunView = (ProgressRunView) findViewById(R.id.progressRunView);
        progressRunView.setMaxStep(5000);

        btn_run = (Button) findViewById(R.id.btn_run);
        btn_run.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_run:
                progressRunView.start(0,3650);
                break;
        }
    }
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容