1.效果
2.创建QQStepView自定义View类
public class QQStepView extends View {
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);
}
}
3.在res/values创建attas.xml文件,编写自定义属性
<!--自定义QQ运动步数-->
<declare-styleable name="QQStepView">
<attr name="outerColor" format="color"/>
<attr name="innerColor" format="color"/>
<attr name="borderWidth" format="dimension"/>
<attr name="stepTextSize" format="dimension"/>
<attr name="stepTextColor" format="color"/>
</declare-styleable>
4.在布局文件中获取自定义View控件
<com.itjs.myapplication.QQStepView
android:layout_gravity="center"
app:outerColor="#03A9F4"
app:innerColor="#E91E63"
app:borderWidth="6dp"
app:stepTextColor="#E91E63"
app:stepTextSize="16sp"
android:layout_width="80dp"
android:layout_height="80dp"/>
5.获取自定义属性
private int mOuterColor = Color.RED;
private int mInnerColor = Color.BLUE;
private int mBorderWidth = 20;
private int mStepTextSize;
private int mStepTextColor;
private Paint mOutPaint,mInnerPaint,mTextPaint;
private int mStepMax = 100;
private int mCurrentStep = 50;
public QQStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.QQStepView);
mOuterColor = array.getColor(R.styleable.QQStepView_outerColor,mOuterColor);
mInnerColor = array.getColor(R.styleable.QQStepView_innerColor,mInnerColor);
mBorderWidth = (int)
array.getDimension(R.styleable.QQStepView_borderWidth,mBorderWidth);
mStepTextSize =
array.getDimensionPixelSize(R.styleable.QQStepView_stepTextSize,mStepTextSize);
mStepTextColor =
array.getColor(R.styleable.QQStepView_stepTextColor,mStepTextColor);
array.recycle();
mOutPaint = new Paint();
mOutPaint.setAntiAlias(true); //抗锯齿
mOutPaint.setStrokeWidth(mBorderWidth);
mOutPaint.setColor(mOuterColor);
// mPaint.setStyle(Paint.Style.FILL); //画笔实心
mOutPaint.setStyle(Paint.Style.STROKE); //画笔空心
mOutPaint.setStrokeCap(Paint.Cap.ROUND); //圆角
mInnerPaint = new Paint();
mInnerPaint.setAntiAlias(true); //抗锯齿
mInnerPaint.setStrokeWidth(mBorderWidth);
mInnerPaint.setColor(mInnerColor);
// mPaint.setStyle(Paint.Style.FILL); //画笔实心
mInnerPaint.setStyle(Paint.Style.STROKE); //画笔空心
mInnerPaint.setStrokeCap(Paint.Cap.ROUND); //圆角
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true); //抗锯齿
mTextPaint.setStrokeWidth(mBorderWidth); //画笔宽度
mTextPaint.setColor(mStepTextColor);
mTextPaint.setTextSize(mStepTextSize);
}
6.onMeasure()
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//在调用者布局文件中可能wrap_content
//获取模式 AT_MOST 40dp
//宽高不一致取最小值 确保是正方形
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width>height?height:width,width>height?height:width);
}
7.画外圆弧、内圆弧,文字
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int center = getWidth() /2;
int radius = getWidth() /2 - mBorderWidth/2;
//画外圆弧
/**
* 参数一:起点的Y轴坐标
* 参数二:起点的X轴坐标
* 参数三:终点的Y轴坐标
* 参数四:终点的Y轴坐标
*/
RectF rectF = new RectF(center-radius,center-radius
,center+radius,center+radius);
canvas.drawArc(rectF,135,270,false, mOutPaint);
if (mStepMax == 0) return;
// 画内圆弧
float sweepAngle = (float) mCurrentStep/mStepMax;
canvas.drawArc(rectF,135,sweepAngle*270,false, mInnerPaint);
//画文字
String stepText = mCurrentStep+"";
Rect textBounds = new Rect();
mTextPaint.getTextBounds(stepText,0,stepText.length(),textBounds);
int dx = getWidth()/2-textBounds.width()/2;
//基线 baseLine
Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
int dy = (fontMetrics.bottom - fontMetrics.top) - fontMetrics.bottom;
int baseLine = getHeight()/2+dy;
canvas.drawText(stepText,dx,baseLine,mTextPaint);
}
8.动画加载
public void setStepMax(int stepMax) {
this.mStepMax = stepMax;
}
public void setCurrentStep(int currentStep) {
this.mCurrentStep = currentStep;
//不断绘制
invalidate();
}
public class MainActivity extends AppCompatActivity {
private QQStepView qqStepView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
qqStepView = findViewById(R.id.step_view);
qqStepView.setStepMax(4000);
//属性动画
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 3000);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(@NonNull ValueAnimator animator) {
float currentStep = (float) animator.getAnimatedValue();
qqStepView.setCurrentStep((int) currentStep);
}
});
valueAnimator.start();
}
}