在Android中也引入了Java Swing中布局的概念。开发者可使用布局来控制组件中元素的位置和大小等信息。Android中共有下面几种布局方式:线性布局(LinearLayout)、相对布局(RelativeLayout)、表格布局(TableLayout)、框架布局(FrameLayout)、绝对布局(AbsoluteLayout)。其中AbsoluteLayout在Adnroid SDK2.3.3之后已经明确不在支持。

布局概述

在一个Android应用程序中,用户界面通过View和ViewGroup对象构建。Android中有很多种View和ViewGroup,他们都继承自View类。View对象是Android平台上表示用户界面的基本单元。我们所说的布局方式是指一组View元素如何布局,准确的说是一个ViewGroup中包含的一些View怎么样布局。我们要介绍的View的布局方式的类,都是直接或间接继承自ViewGroup类,如下图所示:

其实,所有的布局方式都可以归类为ViewGroup的5个类别,即ViewGroup的5个直接子类。其它的一些布局都扩展自这5个类。

线性布局 LinearLayout:      

线性布局是所有布局中最常用的类之一,也是RadioGroup, TabWidget, TableLayout, TableRow, ZoomControls类的父类。LinearLayout可以让它的子元素垂直(android:rientation=“vertical”)或水平(android:rientation=“vertical”)的方式排成一行(不设置方向的时候默认按照垂直方向排列)。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。 linearLayout中有一个重要的属性 android:layout_weight=“1”,这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。

还记得我们那个发送短信的小例子吗?就是采用了的LinearLayout布局方式,只不过是在LinearLayout中嵌套了一个LinearLayout

布局代码如下:

<?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:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/tv_phone" />
     <!-- 手机号码编辑框 -->
     <EditText
        android:id="@+id/et_phone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/tip_phone"
        android:phoneNumber="true"/>
     <!-- 信息内容标签 -->
     <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/tv_content" />
      <!-- 信息内容编辑框 -->
     <EditText
        android:id="@+id/et_content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/tip_content"
        android:minLines="3"/>
     <LinearLayout
         android:layout_width="fill_parent"
    	 android:layout_height="fill_parent"
    	 android:orientation="horizontal">
    	  <!-- 发送按钮 -->
         <Button
            android:id="@+id/btn_Send"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_send"/>
         <!-- 取消按钮 -->
         <Button
            android:id="@+id/btn_Cancel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_cancel"/>
     </LinearLayout>
 </LinearLayout>

3、RelativeLayout

RelativeLayout 允许子元素指定他们相对于其它元素或父元素的位置(通过ID 指定)。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列,因此如果第一个元素在屏幕的中央,那么相对于这个元素的其它元素将以屏幕中央的相对位置来排列。如果使用XML 来指定这个 layout ,在你定义它之前,被关联的元素必须定义。下面我们使用RelativeLayout 改写一下上面的布局代码,同样实现那个发送短信的小例子的界面:

代码如下:

<?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

     <!-- 手机号码标签 -->
     <TextView
        android:id="@+id/tv_phone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/tv_phone" />

     <!-- 手机号码编辑框 -->
     <EditText
        android:id="@+id/et_phone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_phone"
        android:hint="@string/tip_phone"
        android:phoneNumber="true" />

     <!-- 信息内容标签 -->
     <TextView
        android:id="@+id/tv_content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/et_phone"
        android:text="@string/tv_content" />

     <!-- 信息内容编辑框 -->
     <EditText
        android:id="@+id/et_content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_content"
        android:hint="@string/tip_content"
        android:minLines="3" />

     <!-- 发送按钮 -->
     <Button
        android:id="@+id/btn_Send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/et_content"
        android:text="@string/btn_send" />

     <!-- 取消按钮 -->
     <Button
        android:id="@+id/btn_Cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/btn_Send"
        android:layout_toRightOf="@id/btn_Send"
        android:text="@string/btn_cancel" />

 </RelativeLayout>

RelativeLayout 用到的一些重要的属性: 第一类:属性值为 true 或 false

android:layout_centerHrizontal 水平居中

android:layout_centerVertical 垂直居中

android:layout_centerInparent 相对于父元素完全居中

android:layout_alignParentBottom 贴紧父元素的下边缘

android:layout_alignParentLeft 贴紧父元素的左边缘

android:layout_alignParentRight 贴紧父元素的右边缘

android:layout_alignParentTop 贴紧父元素的上边缘

android:layout_alignWithParentIfMissing 如果对应的兄弟元素找不到的话 就以父元素做参照物

第二类:属性值必须为 id 的引用名”@id/id-name”

android:layout_below 在某元素的下方

android:layout_above 在某元素的的上方

android:layout_toLeftOf 在某元素的左边

android:layout_toRightOf 在某元素的右边

android:layout_alignTop 本元素的上边缘和某元素的的上边缘对齐

android:layout_alignLeft 本元素的左边缘和某元素的的左边缘对齐

android:layout_alignBottom 本元素的下边缘和某元素的的下边缘对齐

android:layout_alignRight 本元素的右边缘和某元素的的右边缘对齐

第三类:属性值为具体的像素值,如 30dip,40px

android:layout_marginBottom 离某元素底边缘的距离

android:layout_marginLeft 离某元素左边缘的距离 离某元素右边缘的距离

android:layout_marginRight

android:layout_marginTop 离某元素上边缘的距离

表格布局(TableLayout)

表格布局,将子元素的位置分配到行或列中。一个TableLayout 由许多的TableRow 组成。其实Android的表格布局跟HTML中的表格布局非常类似,TableRow 就像HTML表格的标记。TableLayout 容器不会显示row 、cloumns 或cell 的边框线。每个 row 拥有0个或多个的cell ;每个cell 拥有一个View 对象。表格由列和行组成许多的单元格。表格允许单元格为空。单元格不能跨列,这与HTML 中的不一样。

布局代码:

<?xml version="1.0" encoding="utf-8"?>
 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:stretchColumns="1">

     <TableRow>
         <TextView
            android:layout_column="1"
            android:text="Open..."
            android:padding="3dip" />
         <TextView
            android:text="Ctrl-O"
            android:gravity="right"
            android:padding="3dip" />
     </TableRow>

     <TableRow>
         <TextView
            android:layout_column="1"
            android:text="Save..."
            android:padding="3dip" />
         <TextView
            android:text="Ctrl-S"
            android:gravity="right"
            android:padding="3dip" />
     </TableRow>

     <TableRow>
         <TextView
            android:layout_column="1"
            android:text="Save As..."
            android:padding="3dip" />
         <TextView
            android:text="Ctrl-Shift-S"
            android:gravity="right"
            android:padding="3dip" />
     </TableRow>

     <View
        android:layout_height="2dip"
        android:background="#FF909090" />

     <TableRow>
         <TextView
            android:text="X"
            android:padding="3dip" />
         <TextView
            android:text="Import..."
            android:padding="3dip" />
     </TableRow>

     <TableRow>
         <TextView
            android:text="X"
            android:padding="3dip" />
         <TextView
            android:text="Export..."
            android:padding="3dip" />
         <TextView
            android:text="Ctrl-E"
            android:gravity="right"
            android:padding="3dip" />
     </TableRow>

     <View
        android:layout_height="2dip"
        android:background="#FF909090" />
     <TableRow>
         <TextView
            android:layout_column="1"
            android:text="Quit"
            android:padding="3dip" />
     </TableRow>
 </TableLayout>

用表格布局需要知道以下几点

  • android:shrinkColumns,对应的方法:setShrinkAllColumns(boolean),作用:设置表格的列是否收缩(列编号从0开始,下同),多列用逗号隔开(下同),如android:shrinkColumns=“0,1,2”,即表格的第1、2、3列的内容是收缩的以适合屏幕,不会挤出屏幕。
  • android:collapseColumns,对应的方法:setColumnCollapsed(int,boolean),作用:设置表格的列是否隐藏
  • android:stretchColumns,对应的方法:setStretchAllColumns(boolean),作用:设置表格的列是否拉伸

框架布局(FrameLayout)

FrameLayout是最简单的一个布局对象。它被定制为你屏幕上的一个空白备用区域,之后你可以在其中填充一个单一对象 — 比如,一张你要发布的图片。所有的子元素将会固定在屏幕的左上角;你不能为FrameLayout中的一个子元素指定一个位置。后一个子元素将会直接在前一个子元素之上进行覆盖填充,把它们部份或全部挡住(除非后一个子元素是透明的)。这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。

由于AbsoluteLayout已经不在支持,所以我们这里也不再介绍。在实际开发中也强烈建议不要使用AbsoluteLayout布局方式,因为不同的手机的分辨率是不同的,不同有固定的像素去摆放组件的位置。同时,每一种布局也有其局限性,所以在实际开发中,我们常常同时嵌套使用一种或多种布局方式,以呈现出更美观的用户界面。

总结:

  • LinearLayout,线性布局方式(真不知道这该怎么翻译,其实很多技术名词还是不翻译的好),这种布局比较常用,也比较简单,就是每个元素占一行,当然也可能声明为横向排放,也就是每个元素占一列。
  • FrameLayout, 帧布局方式,说帧不太容易理解,可以说成是层布局方式,也就是说,在它内部的元素,是一层一层的叠加在一起的。如果用过Photoshop,或者 Flash,这里面的层的概念是和他们一致的。如果最上层的元素是不透明的,并且比下面的元素尺寸要大,那么将看不到下面的元素,只能看到顶层元素。这些 层的顺序是:最新声明的放到最前面。可以这样理解,Android按文件的书写顺序来组织这个布局,先声明的放在第一层,再声明的放到第二层,…,最后声 明的放在最顶层。
  • RelativeLayout, 相对定位的布局方式,这个比较好玩,在元素的位置的时候,使用相对位置,可以相对其他元素,也可以相对这个布局,就像我说:我现在站在pawa和 tempest的中间;或者说,我站在队伍的中间。前者就是相对其他元素来定义位置,后者是相对整个布局来定义位置。
  • TableLayout,表格的布局方式,我真的不忍心翻译Table这个词,翻译成表格,似乎少了一些神韵,这里面的Table和HTML中的Table非常像,就连写法都非常像。
  • AbsoluteLayout,绝对定位的布局方式,在它内部嵌套的元素必须指定具体的位置。在sdk2.3.3之后已经废弃,不推荐使用。