[转载]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>

这时如果你使用以下的布局文件IDE就会报错了

<?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>

因为text和textColor属性在前面的布局文件中已经被声明。

实际上给任何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>

我们另外再加一个入口代码就可以发现可以取得我们自定义声明的值了

posted @ 2011-07-21 23:10  周柯文  阅读(6430)  评论(0编辑  收藏  举报