1.在XML文件中声明UI元素。Android提供了一个简单的XML词汇表,用来对应View类和子类。如那些widget构件和layout布局。
2.在运行时实例化布局元素。你的应用程序能够编程创建View和ViewGroup对象(并且操作它们的属性)
Android框架为声明和管理应用程序UI提供了灵活的方法,你可以使用上述方法之一或两者同时使用。例如,你能够在XML文件中声明应用程序默认的布局,包括将要在布局中显示的屏幕元素和属性。然后你能够在应用程序中添加代码在运行时来修改屏幕对象的状态,包括那些在XML文件中声明的属性。
在XML文件中声明应用程序的UI的优点是它能更好的把应用程序的表现跟控制它们行为的代码分离。你的UI在应用程序代码外部描述,这就意味着你不用修改代码和重新编译就能够修改和调整UI。例如,你能够给不同的屏幕方向、不同的设备屏幕尺寸、和不同语言创建XML布局文件。另外,在XML文件中声明布局使得更容易看清UI的结构,以便更容易调试问题。如,本文档重点教你怎样在XML文件中声明布局。如果你对在运行时实例化View对象感兴趣,请参考ViewGroup和View类说明。
一般对于声明UI元素的XML词汇表都紧密的跟这些类和方法的结构和命名关联。实际上,这种对应是你直接就能猜出XML属性对应的一个类方法,或者猜出类对应的xml元素。但是请注意,不是所有的词汇表都是相同的,在某些情况下,会有轻微的命名差异。例如,EditText元素有一个text属性对应EditText.setText()方法。
提示:在“常见的布局对象”专题中你会学到更多不同类型的布局。
编写XML
使用Android的XML词汇表,你能够快速的设计UI布局和它们包含的屏幕元素,就像用HTML标签创建网页一样方便快捷。
每个布局文件必须包含明确的一个根元素,它必须是一个View或ViewGroup对象。一旦你定义了根元素,就能够添加额外的布局对象和构件等子元素来逐步的构建一个定义整体布局View层次结构树。例如,以下是使用持有TextView对象和Button对象的垂直LinearLayout对象的XML布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
在XML中声明了布局以后,要把带有.xml扩展名的文件保存到你的Android工程的res/layout目录中,以便工程能够正确的编译。
上例中的每个属性会在稍后讨论。
装载XML资源
当编译应用程序时,每个XML布局文件都被编译到一个View资源中,你应该在应用程序的Activity.onCreate()回调的实现代码中装载布局资源。通过调用setContentView()方法来完成View资源的加载,调用这个方法时要用R.layout.layout_file_name格式把引用的布局资源传递给它。例如,如果XML布局被保存在main_layout.xml文件中,应该用以下方式来加载:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
当Activity被启动时,Activity中的onCreate()回调方法被Android框架调用。
属性(Attributes)
每个View和ViewGroup对象都支持它们自己的各种XML属性。某些属性是针对一个View对象的(如TextView对象支持的textSize属性),但是这些属性也会被继承这个类的任何View对象继承。某些属性是所有View对象共有的,因为它们是从根View类继承来的(如id属性),并且还有其他的被认为是“布局参数”的属性,它们是描述View对象的某个布局方向的属性,通常由该对象的父ViewGroup对象来定义。
ID属性
任何View对象都可以有一个跟它关联的整数ID,在布局的层次结构树中唯一的标识这个View。应用程序编译时,这个ID作为一个整数来引用,但是通常这个ID会跟布局XML文件中对应id属性值的字符串关联。这是一个对所有View对象都通用的属性(有View类定义),并且你也会经常使用。以下是它在XML标签中的语法:
android:id="@+id/my_button"
开头的@符指示XML解析器应该解析和扩展这个ID字符串的其余部分,并且标识了它是一个ID资源。“+”号意味着这是一个必须创建的新的资源名,并且要把它添加到我们的资源文件中(R.java文件)。有很多由Android框架提供的ID资源,当引用一个Android资源ID是,不需要“+”号,但必须像下例那样添加android包命名空间:
android:id="@android:id/empty"
带有android包命名空间的地方,说明我们应用的是来自Android.R资源类的一个ID,而不是本地资源类。
为了创建View并能在应用程序中应用它们,通用的模式如下:
1.在布局文件中定义一个View/Widget,并给它分配一个唯一的ID;
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
2.创建一个View对象的实例,并且从布局中获取它(通常是在onCreate()方法中)
Button myButton = (Button) findViewById(R.id.my_button);
在创建一个RelativeLayout对象时,给View对象定义ID是重要的。因为在相对布局中,同级View通过引用唯一ID来定义它们相对与另一个同级View的布局。
ID不需要在整个层次结构树中唯一,单一应该在你要检索的层次结构部分内唯一(因为检索经常是整个层次结构树,所以最好还尽可能的全局唯一)。
布局参数
名称为layout_something的XML布局属性给View对象定义了适合它驻留的那个ViewGroup对象的布局参数。
每个ViewGroup类都实现了一个嵌套类,这个类继承了ViewGroup.LayoutParams。这个子类包含了给每个子View定义尺寸、位置的属性类型,以便子View队形适应这个ViewGroup对象。如图1所示,父ViewGroup给每个子View(包括子ViewGroup)定义到了布局参数:
图1. 带有跟每个子View关联的布局参数的View层次结构图
注意,每个LayoutParams子类都有它自己的用于设置值的语法。每个子元素都必须定义适合它的父元素的LayoutParam子类,尽管它也可以给它们自己的子元素定义不同的LayoutParam子类。
所有的ViewGroup都包含一个宽度和高度(layout_width和layout_height属性),并且每个View都要定义定义它们。许多LayoutParam类也包含了可选的边距和边框等属性。
你可以通过精确的测量来指定宽度和高度,虽然不可能经常这样做。更多的,你会使用以下方式来设定宽度和高度:
1.wrap_content会告诉你View,它的尺寸是由它的内容来决定的;
2.fill_parent(在API级别8中推荐match_parent)会告诉你的View,它会变得与它的父ViewGroup所允许大小一样大。
一般情况下,不推荐使用绝对单位来指定布局的宽度和高度,相反,要使用相对计算,如分辨率无关的像素单位(dp),wrap_content或fill_parent是比较好的方法,因为它有助于让你的应用程序在各种尺寸的设备屏幕上显示。
布局位置
一个View就是一个矩形,它用矩形的左顶点坐标来表述它的位置(left和top),并且用width和height来表述它的两边的尺寸。位置和尺寸的计量单位是像素。
通过调用getLeft()和getTop()方法来或取一个View的位置。getLeft()方法返回值代表了这个View的左边距或X点坐标。getTop()方法的返回值代表了这个View的上边距或Y点坐标。这两个方法的返回值都是相对它的父元素的位置,如,当getLeft()方法返回20时,就意味着这个View对象被定为在距离它的父元素的左边缘的右边20个像素的位置。
另外,还有几个便利的方法,从而避免不必要的计算,分别是getRight()和getBottom()。这两个方法返回了这View对象的右下点坐标。例如,调用getRight()方法等同于getLeft()+getWidth()的计算结果。
尺寸、填充方式和边缘
一个View对象的尺寸用宽和高来表述。一个View对象实际上有两对宽和高的值。
第一对是被叫做测量宽度和测量高度。这两个尺寸定义了一个View对象在它的父元素中想要的大小。测量尺寸能够通过调用getMeasuredWidth()和getMeasuredHeight()方法获得。
第二对被简单的叫做宽度和高度,或者某些时候被叫做描画宽度和描画高度。这两个尺寸定义了这个View对象在屏幕上的实际描画和布局尺寸。这两个值可以但不必区分与测量宽度和高度。通过调用getWidth()和getHeight()方法能够获得View对象的宽度和高度。
要计算View对象的尺寸,需要计算它们的填充方式。填充方式以像素为单位,代表了View对象的左顶点到右下点之间的矩形区域。填充方式能够被用于View对象内容的偏移(通过指定偏移像素)。例如,左边填充方式是2的时候,View对象的内容会被推到距离这个对象左边缘右边2个像素的位置。填充方式能够调用setPadding(ing, int, int, int)方法来设置,并且通过调用getPaddingLeft()、getPaddingTop()、getPaddingRight()、getPaddingBottom()方法来查询。
尽管一个View对象只能够定义填充方式,而不提供任何对边缘的支持,但ViewGroup提供这样的支持。更多的信息请参考ViewGroup和ViewGroupMarginLayoutParams类。