1.3构建一个简单的用户界面
Android应用程序的图形用户界面,建立在视图(View)
和视图组(ViewGroup)
对象的层次结构上。视图对象通常是UI小部件(weidget),如按钮或 文本字段;而视图组
对象是无形的视图容器,定义子视图的布局,如在一个网格或垂直的列表中。
Android提供了一个XML对照表来对应视图和视图组的子类,这样你就可以在XML中使用的UI元素的层次结构来定义你的UI。
图1。分支上的视图组对象是如何布局和包含其他视图对象的示意图
可替换的布局
在XML中声明UI布局,而不是在运行时代码中声明,是由于一些非常有用的原因。但它特别重要的原因是,这样你就可以为不同的屏幕大小创建不同的布局。例如,您可以创建两个版本的布局,并告诉系统在“小”屏幕上使用一个而在其他“大”屏幕上使用另一个。欲了解更多信息,请参阅类支持不同的设备。
在本课中,您将在XML中创建一个包含一个文本字段和一个按钮的布局。在下面一课,当按钮被按下时,你会响应把文本字段中的内容发送到另一个活动。
创建一个线性布局
从res/layout/
目录打开activity_main.xml
文件。
注:在Eclipse中,当你打开一个布局文件,首先会显示图形布局编辑器。这是一个编辑器,帮助您使用所见即所得的工具构建布局。在这一课中,你会直接使用XML,所以点击activity_main.xml的标签在屏幕底部打开XML编辑器。
当你创造了这个项目时,你选择的的BlankActivity模板包括 activity_main.xml
的
文件与一个RelativeLayout根视图和一个TextView子视图。
首先,删除<TextView>元素和改变<RelativeLayout>元素<LinearLayout>。然后添加 android:orientation
属性,将其设置为“
横向”
。结果看起来像这样:
<?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">
</LinearLayout>
LinearLayout是一个
视图组(ViewGroup的
一个子类),它根据android:orientation
属性,将子视图按垂直或水平方向布局。LinearLayout的每一个子视图将
以XML中的顺序出现在屏幕上。
另外两个属性,android:layout_width
和android:layout_height
,对所有的视图都是必须的,用来指定它们的大小。
因为LinearLayout是在布局中的根视图,它应该充满整个应用程序屏幕区域,通过设定的宽度和高度为“match_parent”
即可实现
。此值声明视图的宽度或高度应该展开来匹配父视图的宽度或高度。
对于布局属性的更多信息,请参阅布局指南。
添加一个文本字段
要创建一个用户可编辑的文本字段,在<LinearLayout>
元素中添加一个<EditText>。
像每一个视图对象那样,你必须定义某些XML属性来指定的EditText对象的性质。以下是它在<LinearLayout>元素中的声明方法:
<EditText android:id="@+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
关于资源对象
资源对象仅仅是一个简单唯一的整数名称,它与某个应用程序资源关联起来,如位图,布局文件或字符串。
每个资源都有一个相应的资源对象,这些对象在项目的gen/R.java
文件中
定义。您可以使用R
类中的对象名称来指向你的资源,例如你需要为android:hint
属性指定一个字符串值。您还可以创建任意的资源ID,使用android:id
属性关联到一个视图,然后允许你通过它从其他代码来引用该视图。
每次编译您的应用程序时,SDK工具会生成R.java
文件
。您永远不应该手动修改这个文件。
欲了解更多信息,请阅读“提供资源”指南。
关于这些属性:
它为视图提供了一个唯一的标识符,你可以用它在您的应用程序代码中引用该对象,如读取和操纵的对象(你会在下一课中看到)。
当你从XML中引用任何资源对象时,at符号(@
)都是必须的。它后面是资源类型(在本例中是id),斜线,然后是资源名称(edit_message
)。
只有当你首次定义资源ID时,资源类型之前的加号(+
)才是必要的。当你编译应用程序,SDK工具使用ID名称在项目的gen/R.java
文件中
创建一个新的资源ID,
这个资源ID指向EditText元素。一旦资源ID以这种方式声明过,其他对此ID的引用都不需要加号。只有当指定一个新的资源ID时使用加号是必要的,而对于字符串或布局这些具体资源是不需要的。更多信息参见资源对象。
android:layout_width
和android:layout_height
不使用特定尺寸的宽度和高度,而用“wrap_content”
指定视图应该实际大小来适应内容。如果改为使用“match_parent”
,那EditText元素会填满屏幕,因为它要匹配父元素LinearLayout的大小
。更多信息请参阅布局指南。
这是一个文本字段为空时要显示的默认的字符串。不使用硬编码的字符串值,“@string/edit_message”
的值指向一个单独文件中定义的字符串资源。因为它指向的是一个具体的资源(不只是一个标识符),它并不需要加号。但是,因为你还没有定义字符串资源,你首先会看到一个编译错误。你会在下一节中通过定义字符串来修正这个问题。
注:此字符串资源使用相同的名称作为元素的ID: edit_message
。然而,资源总是根据资源类型划分的(如ID
或字符串
),所以使用相同的名称不会发生冲突。
添加字符串资源
当你需要在用户界面中添加文本时,你应该总是指定每个字符串作为一种资源。字符串资源,让您在一个单一的位置管理所有UI文本,这可以更容易找到并更新文本。外部化字符串还允许您为不同语言的每个字符串资源提供替代定义,实现应用程序本地化。
默认情况下,你的Android项目包括res/value/strings.xml
字符串资源文件 。添加一个新的字符串名为“edit_message”
,
并将其值设置为“Enter a message” (你可以删除“hello_world”字符串)。
在这个文件中,顺便为将要添加的按钮添加一个“Send”字符串,叫 “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="menu_settings">Settings</string>
<string name="title_activity_main">MainActivity</string>
</resources>
对于使用字符串资源为您的应用程序本地化为其他语言的更多信息,请参阅支持不同的设备 课程。
添加一个按钮
现在添加一个<button>到
布局中,紧随 <EditText>元素:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send" />
高度和宽度都设置为“wrap_content”
,
所以按钮是适应文本需要的实际大小。此按钮并不需要的 android:id属性,因为它不会在活动代码中被引用。
输入框中填写屏幕宽度
根据目前设计的布局,EditText和Button
部件只需要以适合其内容的大小显示,如在图2中所示。
图2。EditText和Button部件的宽度设置为 “wrap_content”
。
对于按钮这工作得很好,但文本字段则不一样,因为用户可能会输入较长的东西。所以,较好的做法应该是把文本字段填充在全部未使用的屏幕宽度上。你可以在LinearLayou内使用权重属性做到这一点 ,即指定android:layout_weight
属性。
权重值是一个数字,它指定每个视图相对于同级视图对剩余空间所占的比例。这有点像在饮料配方中各种成分的数量:“2份伏特加,1份咖啡利口酒”是指饮料中三分之二是伏特加。例如,如果你给一个视图的权重值为2而另外一个的权重值为1,那么总和是3,所以第一个视图填充的剩余空间的2/3,第二个视图填充剩下的部分。如果您添加了第三个视图,并给它一个权重为1,那么现在第一个视图(权重为2)将得到1/2的剩余空间,而剩下的两个各占1/4。
所有视图的默认权重为0,所以如果你只对某一个视图指定的权重值大于0,等其它所有视图分配好它们需要的空间后,这个视图就会填充所有的剩余空间。因此,要在你的布局中给EditText元素填充所有剩余空间,只需要把它的权重设为1,让按钮保持没有权重。
<EditText
android:layout_weight="1"
... />
为了提高布局的效率,当你指定部件权重时,你应该把EditText宽度设为零(0DP)。把宽度设为零可以提高布局的性能,是因为使用“wrap_content”
作为宽度,系统计算的宽度最终是无关紧要的, 因为权重值会要求通过计算另一个宽度(即Button的宽度,译者注)来填充剩余的空间。(这句比较绕口,附上原文:Setting the width to zero improves layout performancebecause using"wrap_content" asthe width requires the system to calculate a width that is ultimatelyirrelevant because the weight value requires another width calculation to fillthe remaining space.)
<EditText
android:layout_weight="1"
android:layout_width="0dp"
... />
图3显示了当你将所有的权重赋给EditText元素时的结果。
图3EditText部件获得所有布局的权重,所以填充了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工具创建项目时产生的默认的活动类指定此布局,所以你现在可以运行应用程序来查看结果:
· 在Eclipse中,从工具栏中单击“运行” 。
· 或从一个命令行,切换到你的Android项目的根目录并执行:
· ant debug
adb install bin/MyFirstApp-debug.apk
接下来的一课中,你可以学习如何响应按钮按下,读取的文本字段的内容,启动另一个活动,等等。