Android开发指南中文版(九)User Interface-XML Layouts

定义布局

布局指的是Activity中的UI的结构。它定义了布局结构并持有所有用户能看到的元素。你可以有两种方式来定义你的布局:

  • 在xml中定义UI元素。Android提供了一整套和各种View类对应的易懂的xml语法,例如各种widget和layout等。
  • 在运行时初始化Layout元素。你的应用程序可以使用代码创建View和ViewGroup对象。

Android框架通过这两种方法并存的方式提供了灵活的UI定义方式。例如,你可以在xml里定义你的应用程序的默认布局,并在运行时中修改屏幕上的对象。

在xml中定义UI的好处是它让你更好的将应用程序的外观和控制行为的代码分开。你的UI描述在应用程序的代码之外,这意味着你可以在不修改代码和重新编译的前提下修改UI。例如,你可以为不同的屏幕朝向,不同的屏幕大小和不同的语言设定不同的布局。另外,在xml中定义布局使得你的UI更加直观和容易调试(xml的结构比java代码更清晰)。本文介绍如何在xml中定义布局。

总的来说,定义UI的xml词汇和相应的类名、方法名是紧密相关的;xml的元素名对应类名,而xml的属性名对应方法名。事实上,它们之间的关系通常非常直接以至于你可以从xml属性名猜出方法名,或者从xml元素猜出java类名。然而,注意不是所有的词汇都是相同的。在某情况下二者的命名有些小的区别。例如,EditText元素有一个text属性对应于一个叫做EditText.setText()的属性。

  • Eclipse的ADT插件给你提供了xml中的布局预览——打开xml文件,并选择layout标签。
  • 你也可以尝试一下层次浏览器工具(在sdk/tools下),用来调试布局——它显示了布局属性值,根据画出线图来表示padding/margin以及渲染后的view的外观。
  • layoutopt工具可以让你快速分析你的布局和层次是否有效率和其它的问题。

Write the XML

使用Android的xml词汇,你可以很快设计UI布局和它包含的各种屏幕元素,就像使用HTML来创建网页一样——使用一系列嵌套的元素。

每个布局文件必须包含一个根元素,该元素必须是一个View或者ViewGroup对象。一旦你定义了根元素,你就可以加入额外的布局对象或者widget作为其子元素,逐渐构成你的完整布局。例如,这里有一个使用从上到下的LinearLayout布局,它包含了一个TextView和一个Button:

<?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定义了布局之后,将它保存在Android工程的res/layout目录中才能正确编译。

Load the XML Resource

当你编译你的工程时,每个xml布局文件被编译成一个View资源。你应该在应用程序代码中加载这些布局资源,在Activity.onCreate()回调函数的实现中。调用setContentView(),并将布局资源的引用R.layout.layout_file_name传给它。例如,如果你的布局xml文件名为main_layout.xml:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView.(R.layout.main_layout);
}

onCreate()在你的Activity启动时被调用。

Attributes

每个View和ViewGroup对象都支持它们各自的xml属性。有些属性只对某一种View对象有效(例如,TextView支持textSize属性),这些属性对继承这些view的对象也有效。有些属性对View对象普遍有效,因为它们继承于View基类(例如Id属性)。还有的属性被认为是“布局参数”,用来描述View对象的布局属性。

ID

任何View对象可能会有一个整数ID和它相关联,在一棵树中唯一的指定一个View对象。当应用程序被编译时,该id被当做一个整数处理,但是该ID一般是在布局xml里作为一个字符串出现,作为id属性的值。这是一个所有View对象都有的xml属性(由View基类定义)。在xml标签中定义一个id的语法如下:

android:id="@+id/my_button"

字符串开始的@记号告诉xml解析器应该将后面的部分展开并将其识别为一个ID资源。+表示这是一个新的资源名称,必须将其加入我们的资源集(R.java)。有一些其它的ID资源是由Android框架提供的,当引用它们时,不需要使用+符号,但必须加上Android包名称空间,像这样:

android:id="@android:id/empty"

有了Android包名称空间,我们现在指向的是android.R资源类的对象,而不是本地资源类中的对象。

为了创建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);

为View对象定义id,在创建RelativeLayout(相对布局)时是很重要的。在一个相对布局中,兄弟View(位于树结构的同一层的两节点)可以定义它们相互之间的的相对位置,这需要id来标识View对象。

一个ID不需要在整个树中唯一,但它必须在你正在搜索的树的部分中唯一(常常就是整个树,因此最好尽量使用唯一的id)。

Layout Parameters

名称为layout_something的xml布局属性定义了一个View在它所在的ViewGroup中的布局参数。

每个ViewGroup类实现一个嵌套类,该类是ViewGroup.LayoutParams的子类。该类包含了定义每个子View大小和位置的属性。如下图所示,父view group定义了子view的布局参数:

注意每个LayoutParams子类有着它自己的设置值的方法。每个子元素必须定义和其父元素相应的LayoutParams,尽管它可以对它自己的子元素定义不同的LayoutParams。

每个view group包含一个宽度和高度(layout_width和layout_height),每个view必须定义它们。很多LayoutParams也包括可选的margin(空白)和border(边界)。

你可以使用精确值来指定宽度和高度,尽管你可能很少这样使用。更常见的是,wrap_content和fill_parent:

  • wrap_content把view对象的大小设为和它的内容相合适。
  • fill_parent (renamed match_parent in API Level 8) 尽可能的大将其父对象填满。

Layout Position

view的几何性质就是它所在矩形的几何性质。一个view的位置用一对left和top坐标表示,两个长度用width和height来表示。位置和长度的单位是像素。

通过调用getLeft()和getTop()可以得到一个View的位置。这两个方法返回的是相对于其父元素的位置,例如,如果getLeft()返回20,则表示它和其直接父元素的左边界的距离是20像素。

另外,有一些方法的存在只是为了写程序的方便,如getRight()和getBottom()。getRight()和getLeft()+getWidth()的作用是一样的。

Size, Padding and Margins

一个view的大小使用宽度和高度来描述。一个view实际上有两组高度和宽度值。

第一组成为测量宽度和测量高度。这些长度定义了一个view希望在它的父view中的大小。测量长度可以使用getMesuredWidth()和 getMeasuredHeight()来得到。

第二组为宽度和高度,有时被成为绘制宽度和绘制高度。这些长度定义了view在屏幕上的实际大小。这些值可能和测量长度不同。它们可以通过getWidth()和getHeight()得到。

为了测量它的长度,一个view将它的padding考虑在内。padding使用像素来表示,可以设定上下左右各个方向上的padding。padding可以用来将view产生一个位移。例如,一个2像素的左padding将使view向右偏移2个像素。可以使用setPadding(int,int,int,int)来设定,由getPaddingLeft(), getPaddingTop(), getPaddingRight() 和 getPaddingBottom()来获取。

虽然一个view可以定义一个padding,但它并不支持margin。view group支持margin。

posted on 2012-01-05 11:09  蓝风笨笨  阅读(501)  评论(0编辑  收藏  举报

导航