《创建一个简单的用户界面》
Android应用程序的图形用户界面建立在View
(视图)和 ViewGroup
(试图组)层上。 View
对象是常见的界面widgets(控件),例如 buttons(按钮)
或者 text fields (输入框)。ViewGroup
对象
是不可见的视图容器,通常定义子视图的布局,比如说网络型布局或者垂直列表布局。
Android 提供一种XML 语法,相当于View
和 ViewGroup
的子集。所以你可以在XML里利用UI元素的层次结构定义自己的界面。
选择布局
用XML说明UI布局而不用代码有很多原因,最大的原因就是能够对不同的屏幕创建不同的布局。比如说,你可以创建两个版本布局,然后告诉系统一个是用在小屏幕上的,一个是用在大屏幕上的。如需了解更多内容,请点击 Supporting Different Devices。
图 1. 图解ViewGroup对象的布局分支里含有另一个
ViewGroup对象。
在本节课中,你将用XML语言创建一套布局,他会包含一个文本输入框和一个按钮。在下节课中,你就可以使这个按钮在被按下的时候把文字发送给另一个Activity。
创建一个线性布局
在 res/layout/
目录里打开 activity_main.xml
文件。
注意: 在 Eclipse里, 当你打开一个布局文件时,首先看到的是图形界面编辑器,它会帮你用WYSIWYG 工具创建布局。在本节课中,你会直接用XML语言工作,所以打开XML编辑器中在点击上方的activity_main.xml选项卡。
你选择的空白Activity模版包括了activity_main.xml
文件, 里面有 RelativeLayout
(相对布局)根视图和一个 TextView子视图
。
首先,删除<TextView>
部分并且将<RelativeLayout>(相对布局)
换成 <LinearLayout>(线性布局)
。之后添加 android:orientation
属性并设置为"horizontal"
。
改变的结果看起来应该是这样的:
<?xml version="1.0" encoding="utf-8"?> |
LinearLayout
是一个视图组( ViewGroup的子集
)
,会将子视图垂直排列或水平排列, 按照android:orientation
属性说明,
在XML里的 LinearLayout的每一个子集
都会有序的在屏幕上出现。
另外的两个属性,android:layout_width
和android:layout_height
,是用来申明后面所有视图大小的。
由于 LinearLayout
是布局的根视图,它应当充满整个屏幕空间,所以才把应用的宽和高设置成"match_parent"
。这个值声明了视图的宽和高应当与父视图的宽和高匹配。
布局属性的更多信息,详见Layout guide。
添加一个文本框
添加一个可编辑的文本框(输入框),要在<LinearLayout>
里添加一个<EditText>
元素。
像任一 View
(视图),你必须为EditText
定义某些XML
属性,以下是你要在 <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
class (R类)中用对象的名称引用你的资源文件,例如你需要为android:hint
属性制定一个字符串值。您还可以创建任意的资源ID,这些资源用android:id
属性联系在一起,从而允许你在其他代码里引用它。
SDK 工具在你每次编译应用程序的时候都会自动生成R.java
文件,你不能手动修改这个文件。
更多信息,移步Providing Resources.
关于这些属性:
android:id
- 他为视图提供了独一无二的标识,它使你可以从你的应用程序代码里引用对象,比如说读取和操作对象(你将会在下节课中学习到)。
当你在XML里引用任何资源的时候,必须加上at 符号 (
@
) 。 之后要加上资源类型(在这里类型是是id
),斜线, 然后是资源名称(edit_message
)。资源类型后的加号(
+
) 只用在你第一次定义资源的时候。当你编译的时候,SDK工具会用ID名字在项目的gen/R.java
文件里创建一个新的资源ID来引用EditText
,一旦资源ID是用这种方式定义的,以后在引用就不用再加上加号了。只有当申明一个新的资源ID并且不需要具体的资源的时候才会用加号,比如说申明字符串或布局。 在上面你可以看到关于资源对象的更多信息。 android:layout_width
andandroid:layout_height
- 用
"wrap_content"
值而不是对长度和宽度是用特定大小,是因为视图只需要达到足够填满整个父视图就够了。用"match_parent"
,EditText
会填满屏幕, 因为它将匹配父LinearLayout
的大小。 android:hint
- 这是当文本框空的时候默认显示的字符串。
"@string/edit_message"
在单独文件里引用了一个字符串资源,而不直接使用硬编码的字符串值, 是由于这里引用了一个具体的资源(不仅仅是一个标识符),同理这里不需要加号。另外,由于你还没有定义字符串资源,你会看到一个编译错误,但你会在下节课定义字符串的时候修复它。注意: 这里的字符串名字和ID一样,都是:
edit_message
. 通常应用资源的类型都是由资源的类型定义的,例如id
或string
。所以这里是用一样的名字不会引起冲突。
添加字符串资源
当你需要在界面中添加文本时,你应当把每一个字符串当作资源来申明。字符串资源文件使你能够在一个位置管理所有的界面文本,这使你更容易找到并修改文本。字符串的外部化可以使应用程序通过替换定义的字符串资源而支持多种语言。
默认情况下,你的Android项目里面已经包含了一个字符串资源: res/values/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> |
想了解更多关于使用string resources支持多种语言的信息,移步Supporting Different Devices class.
添加一个按钮Add a Button
现在在布局里<EditText>
后面添加 <Button>
:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_send" /> |
宽度和高度都设置为"wrap_content"
,这样按钮的大小决定于按钮文字的多少。这个按钮不需要android:id
属性,所以它不能被activity 代码引用。
Make the Input Box Fill in the Screen Width
目前EditText
和 Button
控件的布局都是内容自适应的,如图二:
图 2. EditText
和 Button
空间的宽度设置值都是"wrap_content"。
按钮看起来还好,但是文本输入框看起来就不太好,这是因为用户有可能输入的更长。所以这两个空间宽度正好填满屏幕宽度。你可以通过在 LinearLayout添加权重属性
来达到这样的效果,这需要你指定android:layout_weight
属性。
权重值是一个数值,这个数值会指定每个视图相对于兄弟视图占剩余空间的多少。这有点像在饮料配方的成分占了量:“2份伏特加酒,1份咖啡利口酒。” 这意味着饮料的三分之二是伏特加,如果你给一个视图的权重是2而另一个视图的权重是1,那么和就是3。所以第一个视图填充剩余视图三分之二,另一个则填充剩余。如果你再加第三个视图,设置权重为1,那第一个视图(权重为2)现在就填充剩余空间的1/2。而剩下的两个各获得1/4。
每个视图的默认权重是0,所以你只能指定一个权重值为0的视图,然后他会填充其他视图填充后的剩余的所有空间。所以想要使用EditText
填充剩余空间就给他指定权重为1,按钮不设定权重
<EditText android:layout_weight="1" ... /> |
当你指定权重值的时候,为了提高布局的效率你应该把EditText
的宽改为0dp。把宽设定为0可以改善布局效率,这是由于使用"wrap_content"
作为宽会让系统计算一个最终用不着的值,因为权重值需要另一个宽度计算才能填充剩余空间。
<EditText android:layout_weight="1" android:layout_width="0dp" ... /> |
图三展示你给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,点击工具栏里的 Run (运行)按钮。
- 或者打开命令行程序,把当前目录切换成安卓项目的根目录,然后运行:
ant debug adb install bin/MyFirstApp-debug.apk |
继续学习下节课程你将学会:为按钮添加按下响应,读取文本输入框的内容,开始另一个activity等。