使用 Android Studio 创建 Project 时,默认的 MainActivity 的布局文件 activity_main.xml 如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height=tools:context=".MainActivity">
<TextView
"wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
在使用 Eclipse 的时候,我曾经就有疑问,上面的xmlns:android=”http://schemas.android.com/apk/res/android”是什么意思。这篇博客就是简单的介绍一下 Android XML 文件的命名空间是什么以及如何使用。
###XML namespace xmlns 即 XML namespace,也就是 XML 文件的命名空间,这是 XML 通用的一个特性,并非 Android 的资源文件特有。XML 命名空间使用 URI 引用来标识,是加在 XML 元素和元素的属性上的约束。注意,URI 是 Identifier,所以,虽然通常会有http://的字符出现,但不一定会像 URL 一样指向特定的资源。XML 的元素和元素的属性,属于不同的命名空间,就可以拥有不同的意义,甚至可以进行@R_301_451@,另外这样做也可以防止冲突。
我们可以这样定义 XML namespace:xmlns:aaa=”http://schemas.aaa.com”这样就定义了一个“http://schemas.aaa.com”的命名空间,它的别名是“aaa”
下面是一个简单的同一个 XML 文件里使用多个命名空间的例子:
这样 XML 的解析器就可以根据不同的命名空间来进行解析工作了。其实,这和 Java 中类的全限定名有些类似,可以有相同的类名,只要它们处于不同的包中,就还是两个不同的类,JVM 是通过类的全限定名来加载类的。
###Android 资源文件的命名空间
####xmlns:android=”http://schemas.android.com/apk/res/android” 这是 Android 的 Framework 层解析 XML 布局文件默认的命名空间,android 是它的别名,所以在 View 的属性前都会有android:的前缀,你也可以取其它的名字,但是这个命名空间的字符串标识符是唯一、不可更改的。
####xmlns:tools=”http://schemas.android.com/tools” Android 还有另外一个常用的命名空间,URI是“http://schemas.android.com/tools”,它可以让工具提取 XML 文件的信息,并且在打包 APK 的时候去除掉此命名空间下的元素和属性,这样就不会影响运行时了。 根据 Android Tools 的官网,下面举几个常用的例子:
- tools:ignore这个属性可以用于任意 XML 元素,是以逗号分隔的 Lint 工具检查项目的 ID,它会忽略此元素及其子元素中相应的 Lint 检查。
Used by: Lint
locale用于资源文件的根节点,指定资源的语言或者地区。
- context
Used by: Layout Editor in Studio & Eclipse,Lint
- layout我们通常都是动态使用 Fragment 类的,其实也可以直接在布局文件中使用 fragment 标签,此时,可以使用这个属性查看 Fragment 的对应布局的渲染效果。注意,这只是作为设计阶段的辅助,运行时你可以加载其它任意布局文件。
- listitem | listheader | listfooter
- menu
####Designtime Layout Attributes 既然我们上面说到的命名空间只是在设计时起作用,我们可以更进一步,覆写 Framework 提供的 View 的属性,只是在设计阶段查看界面渲染的效果,打包的时候会被去除,所以不会影响运行时。
要使用这个功能,和上面一样,首先需要在布局的根元素中加入此命名空间的声明。然后,可以把所有原来以android:前缀开始的 View 的属性改为tools:前缀。而且,这两个命名空间下的属性可以同时出现,一个是设计阶段起作用,一个是运行时起作用,互不影响。
再例如,有些 View 的显示与否是运行时动态控制的,这个时候我们可以这样做:
###在 Android 中@R_301_451@命名空间 上面说的都是 Android 的 Framework 和开发工具定义的 XML 命名空间,我们来看看@R_301_451@ XML 命名空间的应用。我们在 Android 的开发中,偶尔会需要@R_301_451@ View,@R_301_451@的 View 都是继承自 Framework 的android.view.View类或者它的子类。这个时候,如果我们想要除了 Framework 提供的属性以外的属性,就会用到@R_301_451@命名空间。
首先,我们继承View类,并提供接受Context和AttributeSet作为参数的构造方法,这样就可以在XML布局中直接使用@R_301_451@ View 了。
如果我们想要@R_301_451@属性,并且可以在 XML 布局文件中直接使用,请遵守以下 4 条:
首先,让我们来@R_301_451@属性,在res/values/文件夹下添加attrs.xml文件,文件的内容如下:
上面的代码定义了两个@R_301_451@属性,showText和labelPosition,它们都属于PieChart的样式。样式的名称虽然不一定非要和@R_301_451@ View 的类名相同,但是有些代码编辑器是通过名称来进行关联的,所以最好是遵循这个习惯。
下面就可以在 XML 布局文件中使用@R_301_451@属性了,但是和 Framework 提供的内置属性不同的是,@R_301_451@属性不是属于http://schemas.android.com/apk/res/android命名空间的,它是属于http://schemas.android.com/apk/res/[your-package-name]命名空间的。下面就是使用@R_301_451@属性的示例代码:
上面我们定义了custom的命名空间别名,当然你也可以使用其它的别名。
当 XML 布局中的 View 对象被创建的时候,它的属性会被封装进 AttributeSet 对象传进此 View 的构造方法。虽然我们可以直接从 AttributeSet 对象读取属性值,但是更好的方法是将 AttributeSet 对象传给obtainStyledAttributes()方法,这个方法会返回一个包含了属性数组的TypedArray对象。下面就是 PieChart 类如何读取属性的: