Android View之阴阳鱼

(一)基本思路

1、绘制最外层空心圆及白色实心圆。

2、绘制左半圆。

3、添加 1/2 上半圆。

4、减去 1/2 下半圆。

5、最后单独绘制两个 1/8 小圆。

(二)阴阳鱼的绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
* 自定义View -- 阴阳鱼
*
* @author [*昨日重现*] lhy_ycu@163.com
* @since version 1.0
*/
public class YYFishView extends View {

private Paint mPaint;
// 左半圆
private Path mLeftCirclePath;
// 上半圆
private Path mTopHalfCirclePath;
// 下半圆
private Path mBottomHalfCirclePath;
// 阴阳鱼绘制区域
private RectF mFishRegion;

// 绘制区域的宽高
private int mWidth;
private int mHeight;

// 最外层圆的半径
private float mRadius;

private Context mContext;

public YYFishView(Context context) {
this(context, null);
}

public YYFishView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
init();
}

// 1、构造(初始化)
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mLeftCirclePath = new Path();
mTopHalfCirclePath = new Path();
mBottomHalfCirclePath = new Path();

mRadius = DensityUtils.dip2px(mContext, 100);
mFishRegion = new RectF(-mRadius, -mRadius, mRadius, mRadius);
}

// 2、测量(控制)View的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = measureDimension(DensityUtils.dip2px(mContext, 250), widthMeasureSpec);
int height = measureDimension(DensityUtils.dip2px(mContext, 250), heightMeasureSpec);
setMeasuredDimension(width, height);// 保存最终测量的宽高
}

// 注意:这里defaultSize参数可由自定义属性传入构造方法拿到,这里暂时写死。
private int measureDimension(int defaultSize, int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;// 指定大小
} else {
result = defaultSize;// 默认大小
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}

// 3、获取绘制区域宽高
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.mWidth = w;
this.mHeight = h;
}

// 4、绘制图形
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 将坐标系移动到画布中央
canvas.translate(mWidth / 2, mHeight / 2);

// 绘制最外层空心圆
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5F);
mPaint.setColor(Color.GRAY);
canvas.drawCircle(0, 0, mRadius, mPaint);

// 绘制最外层实心圆
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.WHITE);
canvas.drawCircle(0, 0, mRadius, mPaint);

// 为防止每次看的效果可能不一致,这里要重置Path
mLeftCirclePath.reset();
mTopHalfCirclePath.reset();
mBottomHalfCirclePath.reset();

// 绘制左半圆
mLeftCirclePath.addArc(mFishRegion, 90, 180);

// 添加 1/2 上半圆
mTopHalfCirclePath.addCircle(0, -mRadius / 2, mRadius / 2, Path.Direction.CW);
mLeftCirclePath.op(mTopHalfCirclePath, Path.Op.UNION);

// 减去 1/2 下半圆
mBottomHalfCirclePath.addCircle(0, mRadius / 2, mRadius / 2, Path.Direction.CW);
mLeftCirclePath.op(mBottomHalfCirclePath, Path.Op.DIFFERENCE);

mPaint.setColor(Color.BLACK);
canvas.drawPath(mLeftCirclePath, mPaint);

// 最后再在Y轴绘制两个小圆
mPaint.setColor(Color.BLACK);
canvas.drawCircle(0, mRadius / 2, mRadius / 8, mPaint);
mPaint.setColor(Color.WHITE);
canvas.drawCircle(0, -mRadius / 2, mRadius / 8, mPaint);
}

}
Hawky wechat
欢迎订阅我的微信公众号
坚持原创技术分享,您的支持将鼓励我继续创作!

分享