4.3 布局

Android SDK定义了多种布局方式以方便用户UI设计。各种布局方式均为ViewGroup类的子类,结构如图4.3所示。本节将对FrameLayout(单帧布局)、LinearLayout(线性布局)、AbsoluteLayout(绝对布局)、RelativeLayout(相对布局)和TableLayout(表格布局)进行简单的介绍。

图4.3 Android SDK布局方式结构图

4.3.1 FrameLayout

FrameLayout又称单帧布局,是Android所提供的布局方式里最简单的布局方式,它指定屏幕上的一块空白区域,在该区域填充一个单一对象,例如图片、文字、按钮等。应用程序开发人员不能为FrameLayout中填充的组件指定具体填充位置,默认情况下,这些组件都将被固定在屏幕的左上角,后放入的组件会放在前一个组件上进行覆盖填充,形成部分遮挡或全部遮挡。开发人员可以通过组件的android:layout_gravity属性对组件位置进行适当的修改。

实例FrameLayoutDemo演示了FrameLayout的布局效果。该布局中共有四个TextView组件,前三个组件以默认方式放置到布局中,第四个组件修改gravity属性后放置到布局中,运行效果如图4.4所示。

图4.4 FrameLayout的布局效果

实例FrameLayoutDemo中的布局文件main.xml的代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent">
        <TextView
             android:id="@+id/text1"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="#00ff00"
             android:textSize="100dip"
             android:text="@string/first"/>



    <TextView
             android:id="@+id/text2"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="#00ffff"
             android:textSize="70dip"
             android:text="@string/second"/>
       <TextView
             android:id="@+id/text3"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="#ff0000"
             android:textSize="40dip"
             android:text="@string/third"/>
       <TextView
             android:id="@+id/text4"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="#ffff00"
             android:textSize="40dip"
             android:layout_gravity="bottom"
             android:text="@string/forth"/>
    </FrameLayout>

其中,

    android:layout_width="wrap_content"
             android:layout_height="wrap_content"

表明FrameLayout布局覆盖了整个屏幕空间。

实例FrameLayoutDemo中的string.xml文件内容如下:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <string name="app_name">FrameLayoutDemo</string>
       <string name="first">第一层</string>
       <string name="second">第二层</string>
       <string name="third">第三层</string>
       <string name="forth">第四层</string>
    </resources>

从运行后的结果可见,前三个被放置到FrameLayout的TextView组件都是以屏幕左上角为基点进行叠加的。第四个TextView因为设置了android:layout_gravity="bottom"属性而显示到了布局的下方。读者可自行将android:layout_gravity属性值修改为其他属性,查看运行效果。

4.3.2 LinearLayout

LinearLayout又称线性布局,该布局应该是Android视图设计中最经常使用的布局。该布局可以使放入其中的组件以水平方式或者垂直的方式整齐排列,通过android:orientation属性指定具体的排列方式,通过weight属性设置了每个组件在布局中所占的比重。

实例LinearLayoutDemo演示了LinearLayout布局的使用方法,效果如图4.5所示。

图4.5 LinearLayout的布局效果

实例LinearLayoutDemo中的strings.xml文件代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
       <string name="app_name">LinearLayoutDemo</string>
       <string name="red">red</string>
       <string name="yellow">yellow</string>
       <string name="green">green</string>
       <string name="blue">blue</string>
       <string name="row1">row one</string>
       <string name="row2">row two</string>
       <string name="row3">row three</string>
       <string name="row4">row four</string>
    </resources>

实例LinearLayoutDemo中的布局文件main.xml代码如下:

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



     <LinearLayout
          android:orientation="horizontal"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:layout_weight="1">
         <TextView
              android:text="@string/red"
              android:gravity="center_horizontal"
              android:background="#aa0000"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:layout_weight="1"/>
         <TextView
              android:text="@string/green"
              android:gravity="center_horizontal"
              android:background="#00aa00"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:layout_weight="1"/>
         <TextView
              android:text="@string/blue"
              android:gravity="center_horizontal"
              android:background="#0000aa"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:layout_weight="1"/>
         <TextView
              android:text="@string/yellow"
              android:gravity="center_horizontal"
              android:background="#aaaa00"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:layout_weight="1"/>
     </LinearLayout>



     <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1">
       <TextView
            android:text="@string/row1"
            android:textSize="15pt"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>
       <TextView
            android:text="@string/row2"
            android:textSize="15pt"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>
       <TextView
            android:text="@string/row3"
            android:textSize="15pt"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>
       <TextView
            android:text="@string/row4"
            android:textSize="15pt"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>
     </LinearLayout>



    </LinearLayout>

该布局中放置了两个LinearLayout布局对象。第一个LinearLayout布局通过android:orientation="horizontal"属性将布局设置为横向线性排列,第二个LinearLayout布局通过android:orientation="vertical"属性将布局设置为纵向线性排列。每个LinearLayout布局中都放入了四个TextView,并通过android:layout_weight属性设置每个组件在布局中所占比重相同,即各组件大小相同。layout_weight用于定义一个线性布局中某组件的重要程度。所有的组件都有一个layout_weight值,默认为0,意思是需要显示多大的视图就占据多大的屏幕空间。若赋值为大于0的值,则将可用的空间分割,分割的大小取决于当前的layout_weight数值同其他空间的layout_weight值的比率而定,例如水平方向上有两个按钮,每个按钮的layout_weight数值都设置为1,那么这两个按钮平分宽度;若第一个为1第二个为2,则可用空间的三分之一分给第一个,三分之二分给第二个。

将LinearLayoutDemo中水平LinearLayout的第四个TextView的android:layout_weight属性赋值为2,运行效果如图4.6所示。

图4.6 修改android:layout_weight属性

LinearLayout布局可使用嵌套。活用LinearLayout布局,可以设计出各种各样漂亮的布局方式。

4.3.3 RelativeLayout

RelativeLayout又称相对布局。从名称上可以看出,这种布局方式是以一种让组件以相对于容器或者相对于容器中的另外一个组件的相对位置进行放置的布局方式。

RelativeLayout布局提供了一些常用的布局设置属性用于确定组件在视图中的相对位置。相关属性及其所代表的含义列举在表4.1中。

表4.1 RelativeLayout布局常用属性

实例RelativeLayoutDemo演示了相对布局的使用方法,其运行效果如图4.7所示。

图4.7 RelativeLayout布局效果

实例RelativeLayoutDemo中的布局文件main.xml代码如下:

    <?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"
        android="http://schemas.android.com/apk/res/android">



       <TextView
            android:id="@+id/label"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello" />



       <EditText
            android:id="@+id/enter"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_below="@+id/label" />



       <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/enter"
            android:text="@string/but1text" />



       <Button
            android:id="@+id/ok"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/button1"
            android:layout_alignParentLeft="true"
            android:text="@string/but2text" />



    </RelativeLayout>

该RelativeLayout布局的过程如下:

步骤01 放置了一个id为label的TextView组件。

步骤02 通过android:layout_below="@+id/label"属性将id为enter的组件EditText放置到了TextView的下面。

步骤03 在布局中加入了一个id为button1的Button,通过android:layout_below="@+id/enter"属性将该Button放置到enter的下面,通过android:layout_alignParentRight="true"属性将Button放置到相对布局的右面。

步骤04 在相对布局中加入一个名为ok的Button,通过android:layout_alignBottom="@+id/button1"属性将该Button底边与button1对齐,通过android:layout_alignParentLeft="true"属性将该Button放置到布局的左边。

4.3.4 TableLayout

TableLayout又称为表格布局,以行列的方式管理组件。TableLayout布局没有边框,可以由多个TableRow对象或者其他组件组成,每个TableRow可以由多个单元格组成,每个单元格是一个View。TableRow不需要设置宽度layout_width和高度layout_height,其宽度一定是match_parent,即自动填满父容器,高度一定为wrap_content,即根据内容改变高度。但对于TableRow中的其他组件来说,是可以设置宽度和高度的,只是必须是wrap_content或者fill_parent。

实例TableLayoutDemo演示了使用TableLayout制作UI的方法,效果如图4.8所示。

图4.8 TableLayout布局效果

实例TableLayoutDemo中strings.xml代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
       <string name="hello">Hello World, TableLayout!</string>
       <string name="app_name">TableLayoutDemo</string>
    <string name="column1">第一行第一列</string>
    <string name="column2">第一行第二列</string>
    <string name="column3">第一行第三列</string>
    <string name="empty">最左面的可伸缩TextView</string>
    <string name="row2column2">第二行第三列</string>
    <string name="row2column3">End</string>
    <string name="merger">合并三个单元格</string>
    </resources>

实例TableLayoutDemo中的布局文件main.xml的代码如下:

    <?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"  >
       <TableRow>
           <TextView
                android:text="@string/column1" />
           <TextView
                android:text="@string/column2"  />
           <TextView
                android:text="@string/column3" />
       </TableRow>



       <TextView
            android:layout_height="wrap_content"
            android:background="#fff000"
            android:text="单独的一个TextView"
            android:gravity="center"/>
    <TableRow>
           <Button
                android:text="@string/merger"
                android:layout_span="3"
                android:gravity="center_horizontal"
                android:textColor="#f00"
                 />
       </TableRow>



    <TextView
            android:layout_height="wrap_content"
            android:background="#fa05"
            android:text="单独的一个TextView"/>
    <TableRow android:layout_height="wrap_content">
        <TextView
             android:text="@string/empty" />
        <Button
             android:text="@string/row2column2" />
         <Button
            android:text="@string/row2column3" />
     </TableRow>
    </TableLayout>

布局文件main.xml在TableLayout布局内添加了两个TableRow和两个TextView,形成了如图4.8所示的效果。从运行效果看,第一行和第五行都没能完全显示。TableLayout布局提供几个特殊属性,可以实现以下特殊效果。比如:


●android:shrinkColumns属性:该属性用于设置可收缩的列。当可收缩的列太宽以至于布局内的其他列不能完全显示时,可收缩列会纵向延伸,压缩自己所占空间,以便于其他列可以完全显示出来。android:shrinkColumns=“1”表示将第2列设置为可收缩列,列数从0开始。

●android:stretchColumns属性:该属性用于设置可伸展的列。可伸展列会自动扩展长度以填满所有可用空间。android:stretchColumns=“1”表示将第2列设置为可伸展列。

●android:collapseColumns属性:该属性用于设置隐藏列。android:collapseColumns=“1”表示将第2列隐藏不显示。


在<TableLayout>标签添加属性android:shrinkColumns="0",再次运行,效果如图4.9所示,可以看出第一行和第五行都完全显示出来。

图4.9 显示完全的效果

4.3.5 AbsoluteLayout

AbsoluteLayout又称绝对布局,放入该布局的组件需要通过android:layout_x和android:layout_y两个属性指定其准确的坐标值,并显示在屏幕上。理论上AbsoluteLayout布局可用以完成任何的布局设计,灵活性很大,但是在实际的工程应用中不提倡使用这种布局。因为使用这种布局不但需要精确计算每个组件的大小,增大运算量,而且当应用程序在不同屏幕尺寸的手机上运行时会产生不同效果。

实例AbsoluteLayoutDemo演示了AbsoluteLayout布局的使用方法,效果如图4.10所示。

图4.10 AbsoluteLayout布局效果

实例AbsoluteLayoutDemo的布局文件main.xml代码如下:

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



       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_x="10px"
            android:layout_y="10px"
            android:text="@string/hello">
       </TextView>



       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_x="80px"
            android:layout_y="80px"
            android:text="@string/action">
       </TextView>



       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_x="150px"
            android:layout_y="150px"
            android:text="@string/hello">
       </TextView>



    </AbsoluteLayout>

其中,

    android:layout_x="80px"
            android:layout_y="80px"

表示将组件放置到以屏幕左上角为坐标原点的坐标系下,x值为80像素,y值为80像素的位置。

在这里简单介绍一下Android系统常用的尺寸类型的单位:


●像素:缩写为px。表示屏幕上的物理像素。

●磅:points,缩写为pt。1pt等于1英寸的1/72,常用于印刷业。

●放大像素:sp。主要用于字体的显示,Android默认使用sp作为字号单位

●密度独立像素:缩写为dip或dp。该尺寸使用160dp的屏幕作为参考,然后用该屏幕映射到实际屏幕,在不同分辨率的屏幕上会有相应的缩放效果以适用不同的分辨率的屏幕。若用px的话,320px占满HVGA的宽度,到WVGA上就只能占一半不到的屏幕了,那一定不是你想要的。

●毫米:mm。

4.3.6 WebView

WebView组件是AbsoluteLayout的子类,用于显示Web页面。借助于WebView,可以方便地开发自己的网络浏览器。此处仅对WebView的最基本用法进行介绍,在后面进行Web App学习时会有更进一步的讲解。

创建Eclipse工程WebViewDemo,为其在AndroidManifest.xml文件中添加Internet访问权限:

    <uses-permission android:name="android.permission.INTERNET" />

在布局文件main.xml中添加一个WebView组件。Main.xml内容如下:

    <?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">



       <WebView
            android:id="@+id/webView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />



    </LinearLayout>

实例WebViewDemo中的Activity文件WebViewDemoActivity.java代码如下:

    package introduction.android.webView;



    import android.app.Activity;
    import android.os.Bundle;
    import android.webkit.WebView;



    public class WebViewDemoActivity extends Activity {
        private WebView webView;



      /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            webView=(WebView)findViewById(R.id.webView1);
            webView.getSettings().setJavaScriptEnabled(true);
            webView.loadUrl("http://www.google.com");
        }
    }

运行效果如图4.11所示。

图4.11 WebViewDemo运行界面