需求
項目中爲了顯示當前訂單的狀態
效果圖
自定義View實現代碼
public class StateView extends View {
private int mCircularColor;
private int mImageColor;
private int mTextColor;
private int mRadius;
private int mState;
float radius;//圓的半徑
int progress = 0;//進度
RectF arcRectF = new RectF();
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public StateView(Context context) {
super(context);
}
public StateView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StateView);
mCircularColor = typedArray.getInteger(R.styleable.StateView_circular_color, Color.RED);
mImageColor = typedArray.getInteger(R.styleable.StateView_image_color, Color.WHITE);
mTextColor = typedArray.getInteger(R.styleable.StateView_text_color, Color.WHITE);
mRadius = typedArray.getInteger(R.styleable.StateView_radius, 80);
mState = typedArray.getInteger(R.styleable.StateView_state, 1);
typedArray.recycle();//回收
radius = dpToPixel(mRadius);
}
public StateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
{
paint.setTextSize(dpToPixel(40));
//paint.setTextAlign(Paint.Align.CENTER);//設置文本居中對齊
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void stareAnimal() {
final ObjectAnimator animator = ObjectAnimator.ofInt(this, "progress", 0, 440);
animator.setDuration(1500);
animator.setInterpolator(new FastOutSlowInInterpolator());
animator.start();
}
public void setState(int state) {
this.mState = state;
}
/**
* 爲了使用動畫來控制進度
*/
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
invalidate();
}
/**
* 爲了使用動畫來控制進度
*/
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
if (progress > 360) {
//畫一個紅色的圓在底部
paint.setColor(mCircularColor);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawCircle(centerX, centerY, radius, paint);
//畫一個黑色的圓逐漸縮小
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeCap(Paint.Cap.ROUND);
float reduce = dpToPixel(progress - 360);
canvas.drawCircle(centerX, centerY, radius - reduce, paint);
Path path = new Path();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(mImageColor);
paint.setPathEffect(new CornerPathEffect(5));//畫線的路徑效果,CornerPathEffect可以將路徑的轉角變得圓滑
if (progress == 440) {//畫一個√
switch (mState) {
case 0:
path.moveTo(centerX - dpToPixel(45), centerY - dpToPixel(0));
path.lineTo(centerX - dpToPixel(20), centerY + dpToPixel(30)); // 由當前位置 (0, 0) 向 (100, 100) 畫一條直線
path.rLineTo(dpToPixel(60), -dpToPixel(50));
canvas.drawPath(path, paint);
break;
case 1:
//畫×
canvas.drawLine(centerX - dpToPixel(30), centerY - dpToPixel(30), centerX + dpToPixel(30), centerY + dpToPixel(30), paint);
canvas.drawLine(centerX + dpToPixel(30), centerY - dpToPixel(30), centerX - dpToPixel(30), centerY + dpToPixel(30), paint);
break;
case 2:
//畫!
canvas.drawLine(centerX, centerY - dpToPixel(40), centerX, centerY + dpToPixel(20), paint);
//畫點
paint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawPoint(centerX, centerY + dpToPixel(50), paint);
break;
}
}
} else {//360度以下
//畫一個圓弧
paint.setColor(mCircularColor);
paint.setStyle(Paint.Style.STROKE);//空心
paint.setStrokeCap(Paint.Cap.ROUND);//設置畫筆筆刷類型 影響畫筆始末端
paint.setStrokeWidth(dpToPixel(15));
arcRectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
canvas.drawArc(arcRectF, 0, progress, false, paint);//畫圓弧
//繪製需要顯示的文字
paint.setColor(mTextColor);
paint.setStyle(Paint.Style.FILL);
// 計算Baseline繪製的起點X軸座標 ,計算方式:畫布寬度的一半 - 文字寬度的一半
String text = (int) progress + "%";
int baseX = (int) (canvas.getWidth() / 2 - paint.measureText(text) / 2);
//int baseX = (int) (centerX);
// 計算Baseline繪製的Y座標 ,計算方式:畫布高度的一半 - 文字總高度的一半
int baseY = (int) (centerY - ((paint.descent() + paint.ascent()) / 2));
canvas.drawText(text, baseX, baseY, paint);
}
}
public static float dpToPixel(float dp) {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
return dp * metrics.density;
}
}
自定義屬性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="StateView">
<!--圓形背景顏色-->
<attr name="circular_color" format="color" />
<!--圓形中圖案顏色-->
<attr name="image_color" format="color" />
<!--進度字體顏色-->
<attr name="text_color" format="color" />
<!--圓的半徑-->
<attr name="radius" format="dimension" />
<!--狀態-->
<attr name="state">
<enum name="complete" value="0" />
<enum name="failure" value="1" />
<enum name="warning" value="2" />
</attr>
</declare-styleable>
</resources>
使用
<com.example.roczheng.customview.view.StateView
android:id="@+id/state"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
app:circular_color="@color/colorAccent"
app:image_color="#ffffff"
app:state="failure"
app:text_color="@color/colorPrimary" />