上一篇Android自定义控件系列一:如何测量控件尺寸 我们讲了如何确定控件的属性,这篇接着也是讲个必要的知识-如何自定义属性。对于一个完整的或者说真正有实用价值的控件,自定义属性是必不可少的。
如何为控件定义属性
在res/values/attrs.xml(attrs.xml如果不存在,可以创建个)中使用<declare-styleable>标签定义属性,比如我想定义个显示头像的圆形的图片控件(AvatarImageView):
01.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
02.
<
resources
>
03.
<
declare-styleable
name
=
"avatarimageview"
>
04.
<
attr
name
=
"src"
format
=
"reference"
/>
05.
<
attr
name
=
"border"
format
=
"dimension"
/>
06.
<
attr
name
=
"borderColor"
format
=
"reference|color"
/>
07.
<
attr
name
=
"borderAlpha"
format
=
"integer"
/>
08.
</
declare-styleable
>
09.
</
resources
>
name="avatarimageview"指定这组属性的名称,一般可以写成控件名称,标识这些属性是某个控件的。<attr>定义具体的属性,如src--定义图片的来源,border--定义控件的边框大小,borderColor--边框颜色等等。format指定属性值的类型,reference是引用类型,如引用图片、引用颜色、引用文字等。dimension是dp值。integer是整形。color是颜色编码,如果颜色编码是在colors.xml中定义的,此时要用reference,如果俩种方式都支持,中间用竖线分割。
如何获得属性值
属性的定义实际上是为了构建控件的,如上例,只有通过src拿到图片才能画,只有拿到border,才知道我要画多大的边框,所以在实例化控件之前必须能够获得属性及属性值。
为此我们必须要重写View的俩个构造方法,通过AttributeSet参数获得属性值:
View(
Context context)
Simple constructor to use when creating a view from code. 用于通过java代码实例化控件时使用 | |
View(
Context context,
AttributeSet attrs)
Constructor that is called when inflating a view from XML. 用于在布局文件中,通过xml代码创建的控件 |
对于第一个构造方法,完全可以通过setXXX()来注入属性,对于上面的属性定义是没有意义,我们着重说下如何获得布局文件中的属性值。
01.
public
AvatarImageView(Context context, AttributeSet attrs) {
02.
super
(context, attrs);
03.
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.avatarimageview);
04.
src = a.getResourceId(R.styleable.avatarimageview_src,
0
);
05.
if
(src !=
0
)
06.
bitmap = BitmapFactory.decodeResource(
this
.getResources(), src);
07.
08.
border = (
int
)a.getDimension(R.styleable.avatarimageview_border, dip2px(
this
.getContext(),
6
));
09.
10.
borderColor = (
int
)a.getColor(R.styleable.avatarimageview_borderColor,
0
);
11.
if
(borderColor ==
0
)
12.
borderColor = a.getResourceId(R.styleable.avatarimageview_borderColor,
0
);
13.
if
(borderColor ==
0
)
14.
borderColor =
0x9F7A97EA
;
15.
16.
borderAlpha = a.getInt(R.styleable.avatarimageview_borderAlpha, -
1
);
17.
}
通过obtainStyledAttributes()方法获得名称avatarimageview下的所有属性的集合TypedArray。通过TypedArray就可以获得具体的属性值了。如上面代码。
如何在布局文件中使用属性
01.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
02.
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
03.
xmlns:my
=
"http://schemas.android.com/apk/res/com.kanyuan.avatarimageview"
04.
android:layout_width
=
"match_parent"
05.
android:layout_height
=
"match_parent"
06.
android:orientation
=
"vertical"
07.
android:gravity
=
"center"
>
08.
<
LinearLayout
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:orientation
=
"vertical"
>
09.
<
com.kanyuan.avatarimageview.AvatarImageView
android:id
=
"@+id/avatarImageView"
my:src
=
"@drawable/head"
my:border
=
"2dp"
android:layout_width
=
"200dp"
android:layout_height
=
"200dp"
/>
10.
<
Button
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_marginTop
=
"20dp"
android:text
=
"改变头像"
android:onClick
=
"changeAvatar"
/>
11.
</
LinearLayout
>
12.
13.
</
LinearLayout
>
假如我的控件定义在了com.kanyuan.avatarimageview包下。
首先要引入命名空间:xmlns:命名空间名称="http://schemas.android.com/apk/res/app的包名",然后通过这个命名空间引用属性,如:my:src="@drawable/head"、my:border="2dp"。之后就可以在构造方法中获得属性值了。
这样就和上篇的测量尺寸的文章接上了,通过获得padding、border等属性来计算控件实际需要多大的空间。
具体关于这个头像控件的完整源码 http://download.csdn.net/detail/shimiso/9217237
==========================================================================================
欢迎加入我们的技术交流群:
Android群: 66756039
JavaEE群: 361579846