一、简述
- 或多或少老哥们都了解自定义View是啥,本篇文章选了一个比较简单的例子来当做示例,希望大佬们能够喜欢。
- 知识点:自定义属性attrs的简单使用,通过继承View重写onDraw方法使用Canvas来绘制,关于Canvas的用法和View基础可以看我前面写的文章。
二、重写onDraw方法
在开始之前,默认老哥您了解Canvas及View的位置参数,如果不了解请到我的博客瞅一眼。
我在处理边距时是将多余的区域平分放到了两侧,也就是相当于内容居中,详细内容可以看代码,注释很详细。
1 |
|
三、供外部类操作属性的公有方法
1 | // 读取圆的半径 |
四、View自定义属性
创建属性文件(res/values/attrs.xml)
1
2
3
4
5
6
7
8
<resources>
<declare-styleable name="ViewZ2View">
<attr name="circle_color" format="color" />
<attr name="radius" format="dimension" />
<attr name="gap" format="dimension" />
</declare-styleable>
</resources>- 上面的XML文件声明了一个名字为ViewZ2View的自定义属性集合。
- name是自定义属性的名字。
- format是自定义属性的类型,color是颜色属性,integer是基本数据类型,除此之外还有很多,可以阅读文档或直接使用as的代码提示。
在布局文件中添加属性
1
2
3
4
5
6
7xmlns:app="http://schemas.android.com/apk/res-auto"
... ...
<com.sdwfqin.sample.view.viewz2.ViewZ2View
... ...
app:circle_color="#ffffff"
app:gap="10dp"
app:radius="10dp" />在代码中读取设置的属性
1 | private void init(Context context, AttributeSet attrs){ |
五、示例代码
Java文件
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
104public class ViewZ2View extends LinearLayout {
private static final String TAG = "ViewZ2View";
private Context mContext;
private int mColor = Color.WHITE;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 要提高精度可以使用float
//圆的半径
private int radius = 10;
//圆之间的间距
private int gap = 10;
public ViewZ2View(Context context) {
super(context);
init(context);
}
public ViewZ2View(Context context, AttributeSet attrs){
super(context, attrs);
init(context, attrs);
}
public ViewZ2View(Context context, int defStyleAttr) AttributeSet attrs, {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context) {
mContext = context;
mPaint.setColor(mColor);
gap = Utils.dp2px(context, 10);
}
private void init(Context context, AttributeSet attrs){
mContext = context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ViewZ2View);
// Color.WHITE为默认颜色
mColor = typedArray.getColor(R.styleable.ViewZ2View_circle_color, Color.WHITE);
radius = typedArray.getDimensionPixelSize(R.styleable.ViewZ2View_radius, radius);
gap = typedArray.getDimensionPixelSize(R.styleable.ViewZ2View_gap, gap);
typedArray.recycle();
mPaint.setColor(mColor);
}
public int getColor() {
return mColor;
}
public void setColor(int color) {
this.mColor = color;
mPaint.setColor(mColor);
// 刷新视图
invalidate();
}
// 读取圆的半径
public int getRadius() {
return Utils.px2dp(mContext, radius);
}
// 设置圆的半径
public void setRadius(int radius) {
this.radius = Utils.dp2px(mContext, radius);
// 刷新视图
invalidate();
}
public int getGap() {
return Utils.px2dp(mContext, gap);
}
public void setGap(int gap) {
this.gap = Utils.dp2px(mContext, gap);
invalidate();
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 获取宽度与高度
int width = getWidth();
int height = getHeight();
//圆的个数
int count;
try {
// 计算可以显示多少个圆
count = (width - gap) / (radius * 2 + gap);
} catch (Exception e) {
count = 0;
Log.e(TAG, "onDraw: ", e);
}
// 圆的直径
int h = (radius * 2);
// 圆以外的长度
int cgap = (width - (count * h));
// 两侧端点的长度,
int x1 = (cgap + gap - (gap * count)) / 2;
// 绘制
for (int i = 0; i < count; i++) {
int x = x1 + radius + (h + gap) * i;
canvas.drawCircle(x, 0, radius, mPaint);
canvas.drawCircle(x, height, radius, mPaint);
}
}
}xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<com.sdwfqin.sample.view.viewz2.ViewZ2View
android:id="@+id/viewz2_main"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="20dp"
android:background="@color/bar"
android:gravity="center"
app:circle_color="#ffffff"
app:gap="10dp"
app:radius="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="抽奖券" />
</com.sdwfqin.sample.view.viewz2.ViewZ2View>