1.分解步驟
- 1.分析效果
- 2.確定自定義屬性,編寫attrs.xml
- 3.在布局中使用
- 4.在自定義view中獲取屬性
- 5.onMeacher()
- 5.ondraw()畫圖 畫外圓弧 畫內(nèi)圓弧 畫文字
- 6.其他處理(動畫效果)
2.具體步驟
- attrs.xml文件 定義需要的控件內(nèi)部屬性變量
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="QQsetView">
<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>
</resources>
- 在layout布局中使用
<com.incall.apps.qqsetview.QQsetView
android:id="@+id/step"
app:outerColor="@color/blue"
app:innerColor="@color/red"
app:stepTextSize="50sp"
app:stepTextColor="@color/red"
app:borderWidth="6dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- 編寫控件類QQsetView.class
public class QQsetView extends View {
private int mOuterColor = Color.BLUE;//外圓環(huán)顏色
private int mInnerColor = Color.RED;//內(nèi)圓環(huán)顏色
private int mBorderWidth = 20;//圓環(huán)寬度
private int mStepTextSize = 16;//文字字體大小
private int mStepTextColor = Color.RED;//文字顏色
private Paint mOutPaint, mInnerPaint, mTextPaint;//外圓環(huán),內(nèi)圓環(huán),文字畫筆
private int mCurrentStep = 0;//當(dāng)前步數(shù)
private int mStepMax = 0;//最大(總共)步數(shù)
public QQsetView(Context context) {
this(context, null);
}
public QQsetView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public QQsetView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public QQsetView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
//4.在自定義view中獲取屬性
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.QQsetView);
mOuterColor = array.getColor(R.styleable.QQsetView_outerColor, mOuterColor);
mInnerColor = array.getColor(R.styleable.QQsetView_innerColor, mInnerColor);
mBorderWidth = (int) array.getDimension(R.styleable.QQsetView_borderWidth, mBorderWidth);
mStepTextSize = array.getDimensionPixelSize(R.styleable.QQsetView_stepTextSize, mStepTextSize);
mStepTextColor = array.getColor(R.styleable.QQsetView_stepTextColor, mStepTextColor);
//定義外弧畫筆
mOutPaint = new Paint();
mOutPaint.setColor(mOuterColor);
mOutPaint.setAntiAlias(true);
mOutPaint.setStrokeWidth(mBorderWidth);
mOutPaint.setStrokeCap(Paint.Cap.ROUND);
mOutPaint.setStyle(Paint.Style.STROKE);//畫筆空心
//定義內(nèi)弧畫筆
mInnerPaint = new Paint();
mInnerPaint.setColor(mInnerColor);
mInnerPaint.setAntiAlias(true);
mInnerPaint.setStrokeWidth(mBorderWidth);
mInnerPaint.setStrokeCap(Paint.Cap.ROUND);
mInnerPaint.setStyle(Paint.Style.STROKE);//畫筆空心
//定義文字畫筆
mTextPaint = new Paint();
mTextPaint.setColor(mStepTextColor);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(mStepTextSize);
//回收
array.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//判斷設(shè)置的何種模式
//獲取模式AT_MOST 40dp
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//高度不一致,取最小值,以確保為正方形
setMeasuredDimension(width > height ? height : width, width > height ? height : width);
}
//5.畫圖 畫外圓弧 畫內(nèi)圓弧 畫文字
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//定義圓心 半徑
int center = getWidth() / 2;
int radius = getWidth() / 2 - mBorderWidth / 2;
RectF rectF = new RectF(center - radius, center - radius, center + radius, center + radius);
//外弧
canvas.drawArc(rectF, 135, 270, false, mOutPaint);
//內(nèi)弧
float sweepAngle = (float) mCurrentStep / mStepMax;
if (sweepAngle == 0) {
return;
}
canvas.drawArc(rectF, 135, sweepAngle * 270, false, mInnerPaint);
//文字
//dx 文字左側(cè)偏移量
String stepText = mCurrentStep + "";
Rect textBounds = new Rect();
mTextPaint.getTextBounds(stepText, 0, stepText.length(), textBounds);
int dx = getWidth() / 2 - textBounds.width() / 2;
//基線baseline
Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
int baseLine = getHeight() / 2 + dy;
canvas.drawText(stepText, dx, baseLine, mTextPaint);
}
//其他,設(shè)置動畫
public synchronized void setmCurrentStep(int mCurrentStep) {
this.mCurrentStep = mCurrentStep;
invalidate();
}
public synchronized void setmStepMax(int mStepMax) {
this.mStepMax = mStepMax;
invalidate();
}
}
- MainActivity類
QQsetView qQsetstep = findViewById(R.id.step);
qQsetstep.setmStepMax(4000);
//屬性動畫
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 3000);
valueAnimator.setDuration(1000);
valueAnimator.setInterpolator(new DecelerateInterpolator());//插值器
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentStep = (float)animation.getAnimatedValue();
qQsetstep.setmCurrentStep((int) currentStep);
}
});
valueAnimator.start();
3.效果圖
進(jìn)度圓環(huán).gif