[转载]Android布局文件中命名空间的解析
android 中View对象的创建可以在代码中创建,也可以在布局文件中声明,在布局文件中声明时,可以对在布局文件中添加属性,如: android:layout_width="fill_parent" 。属性包括两个部分:android和layout_width,android是命名空间,layout_width是属性名,我们可以在View上添加任意不带前缀的属性如:<View android:layout_width="44dip" android:layout_height="0dip" anyproperty="value" />, 上面的代码不会报任何的错误,但是这样做并没有任何的实际意义。
View中要想自己生命的属性有意义,则需要为属性加一个命名空间前缀,在布局文件中直接给View加前缀是不允许的,如:<Button myxmlns:anyproperty="value" /> 这样的代码在IDE中会直接报错,并提示无该命名空间,要想使得该命名空间有效,则需要在使用该命名空间之前生命该命名空间,方式如下:
<View xmlns:myxmlns="ssss" />
有了如上的生命,我们就可以有如下的代码而使得IDE不会报告任何错误:<View xmlns:myxmlns="sss" myxmlns:anyproperty="value" />
在实际应用中大多数的自定义命名空间都声明在第一个元素中,如:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myxmlns="ssss"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
ss="" />
<View myxmlns:sss="sss" />
</LinearLayout>
但这些声明不会使得IDE报错,但其实也是没有任何意义的。因为这里的命名空间的值sss是任意定义的,我们要使得它看起来有意义,我们一般使用如下的值xmlns:myxmlns=""http://schemas.android.com/apk/res/<你的应用程序的包名>",同时我们还需要在values目录下创建一个attrs.xml的文件,文件的内容看起来像这样的:
<resources>
<declare-styleable name="LabelView">
<attr name="text" format="string" />
<attr name="textColor" format="color" />
</declare-styleable>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myxmlns="http://schemas.android.com/apk/res/com.zbkc.custumview"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<View myxmlns:sss="sss" />
</LinearLayout>
他会在 <View myxmlns:sss="ssss" />这一行提示myxmlns的命名空间下sss这个属性
但我们可以使用如下的布局文件而不会报错:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myxmlns="http://schemas.android.com/apk/res/com.zbkc.custumview"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<View myxmlns:text="sss"
myxmlns:textColor="#ffffffff"/>
</LinearLayout>
实际上给任何android自带的控件增加自定义属性都是无意义的做法,但对于自定义的View(继承自View的类)来增加自定义的属性却是有很大的实际意义的,如,我们可能经常看到有如下的声明:
<MyView android:layout_width="fill_parent"
android:layout_height="fill_parent"
myxmlns:anyproperty="value" />
这就是为自定义的View添加了额外的属性,但是刚有了我们前面的声明,并没有什么实际的意义,因为只是做到了声明IDE不报错,并没有任何实际的意义,我们现在要做的就是如何在自定义的View中(注意,只能在自定义的View中来取得这些值)取得我们在布局文件中声明的属性值。
我们下面来写一个稍微完整一点的代码来演示一下完整的过程:
java代码
class LabelView extends View {
private String text;
private int textColor;
public LabelView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LabelView);
text = (String)a.getText(R.styleable.LabelView_text);
textColor = a.getColor(R.styleable.LabelView_textColor, 0xff000000);
Log.i("test", "text:" + text);
Log.i("test", "textColor:" + textColor);
a.recycle();
}
}
Xml声明
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myxmlns="http://schemas.android.com/apk/res/com.zbkc.custumview"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.zbkc.custumview.LabelView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
myxmlns:text="sss"
myxmlns:textColor="#ff00ff00" />
</LinearLayout>