自定義View合輯(4)-太極
為了加強對自定義 View 的認知以及開發能力,我計劃這段時間陸續來完成幾個難度從易到難的自定義 View,並簡單的寫幾篇部落格來進行介紹,所有的程式碼也都會開源,也希望讀者能給個 star 哈
GitHub 地址: https://github.com/leavesC/CustomView
也可以下載 Apk 來體驗下: https://www.pgyer.com/CustomView
先看下效果圖:

一、思路描述
繪製太極 View 的步驟分為以下幾步:
- 繪製一個半徑為 radius 的空心圓
- 將上半圓填充為黑色,下半圓填充為白色
- 在穿過圓心的平行線上,繪製兩個填充色分別為黑白色,半徑為 radius/2 的圓
- 在兩個小圓的圓心上再繪製兩個相反顏色,半徑更小的小圓
繪製過程還是蠻簡單的,總的程式碼也就一百行左右
二、原始碼
/** * 作者:leavesC * 時間:2019/4/26 9:29 * 描述: */ public class TaiJiView extends BaseView { private Paint paint; public TaiJiView(Context context) { this(context, null); } public TaiJiView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public TaiJiView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initPaint(); } private void initPaint() { paint = new Paint(); paint.setAntiAlias(true); paint.setDither(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = getSize(widthMeasureSpec, getResources().getDisplayMetrics().widthPixels); int height = getSize(heightMeasureSpec, getResources().getDisplayMetrics().heightPixels); width = height = Math.min(width, height); setMeasuredDimension(width, height); } private float radius; private float centerX; private float centerY; private float degrees; @Override protected void onSizeChanged(int w, int h, int oldW, int oldH) { w = w - getPaddingLeft() - getPaddingRight(); h = h - getPaddingTop() - getPaddingBottom(); w = Math.min(w, h); radius = w / 2f; centerX = getPaddingLeft() + radius; centerY = getPaddingTop() + radius; } private RectF rectF = new RectF(); @Override protected void onDraw(Canvas canvas) { //稍稍留一點間距 float realRadius = radius - 8; float temp1 = realRadius / 2f; float temp2 = temp1 / 8f; canvas.translate(centerX, centerY); canvas.rotate(degrees); //繪製邊框 paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(0.4f); canvas.drawCircle(0, 0, realRadius, paint); //繪製左右半圓 rectF.set(-realRadius, -realRadius, realRadius, realRadius); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(0); paint.setColor(Color.BLACK); canvas.drawArc(rectF, 90, 180, true, paint); paint.setColor(Color.WHITE); canvas.drawArc(rectF, -90, 180, true, paint); //繪製上邊的白色圓 canvas.save(); canvas.translate(0, -temp1); paint.setColor(Color.WHITE); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(1); canvas.drawCircle(0, 0, temp1, paint); paint.setColor(Color.BLACK); canvas.drawCircle(0, 0, temp2, paint); canvas.restore(); //繪製上邊的黑色圓 canvas.save(); canvas.translate(0, temp1); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(0, 0, temp1, paint); paint.setColor(Color.WHITE); canvas.drawCircle(0, 0, temp2, paint); canvas.restore(); } public float getDegrees() { return degrees; } public void setDegrees(float degrees) { this.degrees = degrees; postInvalidate(); } }