在自定义一个View的时候,为了让View的功能变得强大点,往往我们需要支持自定义属性来支持显示界面中所需要的效果,比如说:android:textColor="#ffffff"这样定义一个属性,可支持显示不同颜色,那么我们在项目中要如何定义?
首先我们需要在res/values目录下新建个attrs的xml文件当然这个名字是可以自定义的,但是不能重复定义一个属性。
<declare-styleable name="myViewAttrs">
<attr name="String" format="string"/>
<attr name="Boolean" format="boolean"/>
<attr name="Integer" format="integer"/>
<attr name="Dimension" format="dimension"/>
<attr name="Reference" format="reference"/>
<attr name="Fraction" format="fraction"/>
</declare-styleable>
其中得name字段表示的是自定义名称
format表示的属性类型可以为boolean, string, integer, dimension, float, reference, color, fraction, enum, flag及其混合。
(1) boolean表示布尔值,调用如 xx:attr1="false"
(2) integer表示整型,调用如 xx:attr1="1"
(3) dimension表示尺寸值,调用如 xx:attr1="42dp"
(4) float表示浮点型,调用如 xx:attr1="0.7"
(5) color表示颜色值,调用如 xx:attr1="#00FF00"
(6) string表示字符串,调用如 xx:attr1="#adbddd"
(7) reference表示参考某一资源id,调用如 xx:attr1 = "@drawable/图片ID"
(8) fraction表示百分数,调用如 xx:attr1="30%"
以上类型定义都为<attr name="attr1" format="xxxtype"/>
(9) enum表示枚举值,定义为
<attr name="enum_attr"> <enum name="horizontal" value="0" /> <enum name="vertical" value="1" /> </attr>
调用如 xx:attr1="horizontal"
(10) flag表示位或运算,定义为
<attr name="windowSoftInputMode"> <flag name = "stateUnspecified" value = "0" /> <flag name = "stateUnchanged" value = "1" /> <flag name = "stateHidden" value = "2" /> <flag name = "stateAlwaysHidden" value = "3" /> <flag name = "stateVisible" value = "4" /> <flag name = "stateAlwaysVisible" value = "5" /> <flag name = "adjustUnspecified" value = "0x00" /> <flag name = "adjustResize" value = "0x10" /> <flag name = "adjustPan" value = "0x20" /> <flag name = "adjustNothing" value = "0x30" /> </attr>
调用如:xx:attr1="stateUnspecified | stateUnchanged | stateHidden"
(11) 混合类型,定义为
<declare-styleable name = "combine_type"> <attr name = "background" format = "reference|color" /> </declare-styleable>
调用如 xx:attr1 = "@drawable/图片ID|#DDFF00"
定义完这么一个属性之后我们就可以在View中使用了,类似为:
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.myViewAttrs);
String name = ta.getString(R.styleable.myViewAttrs_String);
boolean _boolean = ta.getBoolean(R.styleable.myViewAttrs_Boolean, false);
int _integer = ta.getInt(R.styleable.myViewAttrs_Integer, -1);
float _demension = ta.getDimension(R.styleable.myViewAttrs_Dimension, 0);
int _reference = ta.getResourceId(R.styleable.myViewAttrs_Integer, -1);
float _fraction = ta.getFraction(R.styleable.myViewAttrs_Fraction, 1, 1, 0);
System.out.println("Name is = " + name);
System.out.println("_boolean is = " + _boolean);
System.out.println("_integer is = " + _integer);
System.out.println("_demension is = " + _demension);
System.out.println("_reference is = " + _reference);
System.out.println("_fraction is = " + _fraction);
ta.recycle();
是在View中通过context.obtainStyleAttributes方法读取每个属性的值,然后就可以在代码中使用这些自己定义好得属性控制界面显示效果。记得调用ta.recyle()来回收资源。
写好一个View之后我们就可以在xml文件中定义和使用这个View了,当然是把自定义得属性一起使用起来:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:neacy="http://schemas.android.com/apk/res/com.example.testattr"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.testattr.MainActivity" >
<com.example.testattr.AttrView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
neacy:String="Hello World, 你好世界!"
neacy:Boolean="true"
neacy:Integer="17"
neacy:Dimension="99dp"
neacy:Reference="@drawable/ic_launcher"
neacy:Fraction="50%" />
</RelativeLayout>
注意到
xmlns:neacy="http://schemas.android.com/apk/res/com.example.testattr"
其中得neacy字段可自行定义,值为http://schemas.android.com/apk/res/加当前应用的包名,然后就可以在对应的AttrView中定义这些属性。