解析请看这自定义View-仿QQ运动步数进度效果
<?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>
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;
//动态设置扫过的面积(弧的动态效果)
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());
}
/**
* 步数的重新绘制
* @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();
//设置当前的步数并重新绘制
setProgress(currentStep);
Log.e("onAnimationUpdate: ", String.valueOf(currentStep));
}
});
}
}
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;
}
}
}