Android应用的图形化用户界面的构建使用的是View
和 ViewGroup
对象的层次嵌套。 View
对象通常是UI部件,例如 buttons 或者 text fields ,而 ViewGroup
是用来定义它的子布局如何排布的容器,它通常是不可见的,例如一个网格或者一个垂直的列表。
Android提供XML词汇与View或者ViewGroup的子类的对应,这样的话你就可以通过XML元素的层级嵌套来定义你的UI。
另一种布局
使用XML声明UI比在运行时代码中声明更有用处可以在很多地方看出来,尤其是当你为不同的屏幕创建不同的布局时。例如你创建了两个布局,然后告诉系统,其中一个是用于小尺寸的屏幕,另一个是用于大尺寸的屏幕。有关跟多的信息,请查看Supporting Different Devices。
图 1. 插图所示的是ViewGroup对象是如何分支布局并且包含其他的View对象
在这片课程中,你将会使用XML来创建一个包含text field和一个button的布局。在接下来的课程中你就会学习如何响应button的点击事件,当按下button时将text field中的文字发送给另一个Activity。
创建一个线性布局
打开 在 res/layout 目录下 fragment_main.xml
文件。
提示: 在Eclipse中,当你打开一个layout(布局)文件时,首先显示的是布局的图形编辑器。这是一个使用WYSIWYG工具来帮助你编辑界面的编辑器。在本次课程中,你将要学习如何直接使用XML来工作,所以点击界面底部的 fragment_main.xml tab 来打开编辑器吧。
在你创建项目是选择的 BlankActivity 模板中包含了 fragment_main.xml
文件,文件的内容有RelativeLayout
根布局和一个 TextView
子布局。
首先,删除 <TextView>
元素,并且将 <RelativeLayout>
元素改为 <LinearLayout>
。然后添加android:orientation
属性,并将其值设置为 "horizontal"
。就像下面这样:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > </LinearLayout>
LinearLayout
是一个view group (ViewGroup 的子类
) ,它的子布局会以水平或者垂直的方向线性布局,通过 android:orientation
属性来指定。LinearLayout
的子布局将会按照XML文件中的顺序在屏幕上展示。
另外两个属性,android:layout_width
和 android:layout_height
,在所有的View中都需要设置,用来指定布局的宽度和高度。
由于LinearLayout
是根布局,需要通过将其高度设置为"match_parent"
来让它在整个屏幕范围内可见。这个值声明了此布局将会延展它的宽度或者高度来适应它的父布局。
有关更多的信息,请查看 Layout 向导。
添加一个Text Field
要创建一个用户可编辑的text field,需要在 <LinearLayout>
标签内添加<Edit Text>元素。
就像所有View
对象那样,你必须定义某些XML属性来指定EditText
对象的属性。下面向你展示如何在<LinearLayout>
元素中来定义它:
<EditText android:id="@+id/edit_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/edit_message" />
关于资源对象
一个资源对象是与应用资源相关联的简单的唯一的integer类型的名字,例如一个bitmap,layout,string。
每一个资源都会在gen/R.java
文件中有相应的资源对象与其对应。你使用R类的那些对象名称来引用你的资源,例如当你需要为android:hint
属性指定一个字符串类型的值时。你还可以使用android:id
属性随意创建资源ID,这样你就可以在其他的代码中引用这个view。
SDK工具在你每次编译应用时都会生成R.java文件。你一定不要手动修改此文件的内容。
更多资料,请查看Providing Resources。
关于这些属性:
-
它为此view提供了一个唯一的标识,你可以在应用的代码中直接引用它,例如读取和操作这个对象(你将会在下篇课程中学到)。
当你要参照XML文件中其他的对象时,你需要使用(
@
) 。它的后面跟着资源的类型(本例中是id),一个斜杠,然后资源的名称。+这个符号只有在你第一次定义一个资源的ID时才需要加上。当你编译你的应用的时候,SDK工具会通过这个ID名称在gen/R.java文件中创建相应的资源ID来与EditText元素对应。一旦资源ID通过这种方式被定义好,其他引用这个ID不需要使用+号。查看右侧的文字了解更多资源对象。
-
使用"wrap_content"指定view的大小会根据内容来适应,
用来代替直接指定view的大小。如果你希望使用"match_parent",那么
EditText
元素将会占满整个屏幕,应为它会根据父布局LinearLayout
来适应大小。跟多信息,请查看 Layouts 向导。 -
这个属性用于指定当text field为空时显示的内容。最好使用
"@string/edit_message"
这种引用方式来为其赋值,而不要直接在代码中赋值。提示: 这个字符类型和元素ID有相同的名称。然而他们的类型不同,因此同样的名称不会冲突。
android:id
android:layout_width
and
android:layout_height
android:hint
添加一个String资源
当你需要在UI中显示文字的时候,你一定要为每个字符串设置为资源。字符串资源让你把所有的UI上的文字都集中在一个地方管理,让更新文字更简单。这种方式在你为不同语言提供字符串定义时可以为不同的语言实现本地化(国际化)。
在默认情况下,你的项目包含一个字符串资源文件,在res/values/strings.xml
下。添加一个字符串,名字为"edit_message"
,同时将其值设为"Enter a message" 。(你可以删掉"hello_world" 了)
在这个文件中为你即将要添加的button添加一个“Send”的字符串。
strings.xml
应将像下面这样:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">My First App</string> <string name="edit_message">Enter a message</string> <string name="button_send">Send</string> <string name="action_settings">Settings</string> <string name="title_activity_main">MainActivity</string> </resources>
添加一个Button
现在添加一个 <Button>
元素到布局中,紧跟着 <EditText>
元素:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" />
将它的高度设置为"wrap_content"
这样它就只会显示它比要的高度来包裹按钮中的文字。它不需要android:id
属性,因为它不会再其他地方被引用到。
让输入框占满整个屏幕宽度
如图2所示,现在布局中的两个部件EditText
和 Button
都只有必要的大小来适应它们的内容。
图 2. EditText
和 Button
部件的属性设置为"wrap_content"
。
这样对于button能够很好的展示,但是对text field就不一样了,因为用户可能会输入一些更长的文字。因此,让text field占满屏幕的空余部分效果会更好。在LinearLayout中,你可以使用android:layout_weight
属性来指定。
Weight是一个用来指定每个view应该占用的空间的值,相对与同级别的其他的布局。 这工作有点像成分的饮料配方量:“2份伏特加,1份咖啡力娇酒”是指三分之二的饮料是伏特加。例如,如果给一个view的权重为2另一个view的权重为1,则总和是3,那么第一个view填充剩余空间的2/3,第二view填充的其余部分。如果添加了第三个view,并给它一个权重为1,那么第一个布局(权重2)现在占一半的剩余空间,而剩下的两个各得四分之一。
所有view默认的权重是0,因此如果你仅指定一个view的权重大于0,那么它会占满所有其它view剩余的空间。所以,要让EditText填充剩余空间,就只需将它的权重设为1,然后button不设置权重值。
<EditText android:layout_weight="1" ... />
当你指定权重值是,为了提高布局的效率,你应该将EditText的宽度改为0dp。设置宽度为0dp的原因是,它会根据其他的view计算宽度后填充剩余空间,而此时通过宽度为"wrap_content"
来通过系统计算宽度是没有用处的。
<EditText android:layout_weight="1" android:layout_width="0dp" ... />
图 3 展示给EditText设置权重的效果。
图 3. EditText
部件设置了所有的权重,所以它填充了LinearLayout
的剩余空间。
下面是完整的代码:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <EditText android:id="@+id/edit_message" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="@string/edit_message" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" /> </LinearLayout>
这个布局在你创建项目时被SDK工具生成的Activity所引用,所以你可以运行这个应用看看结果:
- 在Eclipse中,在工具栏上点击
。
- 或者在命令行中,改变目录到项目根目录然后执行:
ant debug adb install bin/MyFirstApp-debug.apk