/**
* Created by Cwm on 2018/3/1.
* 仿QQ运动
* 思路分析:
* 1、先画外圆弧
* 2、再画内圆弧
* 3、画内部字体颜色
*/
public class QQSports extends View {
private int mExcircleColor = Color.RED;
private int mFilletColor = Color.BLUE;
private int mBreadth = 20;//20px
private int mFontColor = Color.RED;
private int mFontSize = 40;//20px
//分别是外圆弧、内圆弧、字体画笔
private Paint mExcirclePaint, mFilletPaint, mTextPaint;
//当前步数和总步数 这个要交给调用者去设置
private int mCurrentStep = 3000, mMaxStep = 5000;
public QQSports(Context context) {
this(context, null);
}
public QQSports(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public QQSports(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.QQSports);
mExcircleColor = typedArray.getColor(R.styleable.QQSports_excircleColor, mExcircleColor);
mFilletColor = typedArray.getColor(R.styleable.QQSports_filletColor, mFilletColor);
mFontColor = typedArray.getColor(R.styleable.QQSports_fontColor, mFontColor);
mBreadth = typedArray.getDimensionPixelSize(R.styleable.QQSports_breadth, mBreadth);
mFontSize = typedArray.getDimensionPixelSize(R.styleable.QQSports_fontSize, mFontSize);
typedArray.recycle();
//实例化画笔
mExcirclePaint = new Paint();//外圆弧
mExcirclePaint.setColor(mExcircleColor);//设置颜色
mExcirclePaint.setStrokeWidth(mBreadth);//设置画笔宽度
mExcirclePaint.setAntiAlias(true);//设置抗锯齿
mExcirclePaint.setStyle(Paint.Style.STROKE);//设置画笔空心
mExcirclePaint.setStrokeCap(Paint.Cap.ROUND);//设置画笔笔刷类型 帽子 圆弧两边的小盖子 把圆弧封闭住
mFilletPaint = new Paint();//内圆弧
mFilletPaint.setColor(mFilletColor);//设置颜色
mFilletPaint.setStrokeWidth(mBreadth);//设置画笔宽度
mFilletPaint.setAntiAlias(true);//设置抗锯齿
mFilletPaint.setStyle(Paint.Style.STROKE);//设置画笔空心
mFilletPaint.setStrokeCap(Paint.Cap.ROUND);//设置画笔笔刷类型 帽子 圆弧两边的小盖子 把圆弧封闭住
mTextPaint = new Paint();//文字
mTextPaint.setColor(mFontColor);//设置颜色
mTextPaint.setTextSize(mFontSize);//设置字体大小,不应该设置画笔宽度
mTextPaint.setAntiAlias(true);//设置抗锯齿
}
//重新测量设置View宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取宽高
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//获取模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//在测量宽高时判断模式是否为AT_MOST
if (widthMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.AT_MOST) {
throw new UnsupportedOperationException("Width and height must specify specific values");
}
//在测量宽高时判断是否大于0
if (widthSize <= 0 || heightSize <= 0) {
throw new UnsupportedOperationException("Width and height must be greater than 0");
}
//当宽和高有具体值且大于0,但是宽和高的值不一样时,按照高度走,必须保持一个正方形
//即:
setMeasuredDimension(widthSize > heightSize ? heightSize : widthSize
, widthSize > heightSize ? heightSize : widthSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,@NonNull Paint paint)
* oval 绘制区域
* startAngle 扫描起始角度
* sweepAngle 扫描结束角度
* useCenter 圆弧里边部分是否都是充满颜色 false表示你画圆弧时不需要给圆弧区域把颜色全部填充
* paint 画笔
*/
// float left, float top, float right, float bottom
RectF rectF = new RectF(mBreadth, mBreadth, getWidth() - mBreadth, getHeight() - mBreadth);
canvas.drawArc(rectF, 135, 270, false, mExcirclePaint);
//画内圆弧
if (mMaxStep <= 0) return;
//动态设置内圆角度 使用百分比 必须强转float
float sweepAngle = (float) mCurrentStep / mMaxStep;
canvas.drawArc(rectF, 135, sweepAngle * 270, false, mFilletPaint);
//画文字
String text = mCurrentStep + "";
Rect boundsRect = new Rect();//文字区域
mTextPaint.getTextBounds(text, 0, text.length(), boundsRect);
//x轴位置
int dx = getWidth() / 2 - boundsRect.width() / 2;
//y轴位置 基线baseLine
Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
int baseLine = getHeight() / 2 + dy;
//drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
canvas.drawText(text, dx, baseLine, mTextPaint);
}
/**
* 设置当前步数
* synchronized防止多线程调用
*
* @param currentStep
*/
public synchronized void setCurrentStep(int currentStep) {
this.mCurrentStep = currentStep;
invalidate();//设置步数以后重绘(只能在UI线程调用)
}
/**
* 设置 最大步数
* synchronized防止多线程调用
*
* @param maxStep
*/
public synchronized void setMaxStep(int maxStep) {
this.mMaxStep = maxStep;
}
以下是自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="QQSports">
<!--excircleColor 外圆颜色、filletColor 内圆颜色、
breadth 圆的宽度、fontColor 字体颜色、fontSize 字体大小-->
<attr name="excircleColor" format="color"/>
<attr name="filletColor" format="color"/>
<attr name="breadth" format="dimension"/>
<attr name="fontColor" format="dimension"/>
<attr name="fontSize" format="dimension"/>
</declare-styleable>
</resources>
使用方法 在XML中直接使用或自己添加一些方法在代码中调用,可以自己添加一些动画