从零开始学Android编程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第2篇 布局篇

第3章 Android常见界面布局

在我们所看到的应用程序中,界面都有自己的特点,都有自己的显示方式,这就是本章所要讲的界面布局的功劳。界面的布局在一个Android程序中是很重要的,它可以使一个界面变得美观大方(当然没有大量的图片是做不到的)。

3.1 界面简介

在学习布局之前,先来了解一下Android中的用户界面。在Android系统中有3种方式生成一个屏幕:采用XML布局、通过用户界面接口调用和用代码实现。在Android的应用中,用户界面都是由View和ViewGroup对象组成的。View和ViewGroup有很多种类,它们都是View的子类,下面来看一些View和ViewGroup。

1.View

View类是Android的一个超类,这个类几乎包含了所有的屏幕类型。每一个View都有一个用于绘图的画布,这个画布可以进行任意扩展。在一个View对象中可以处理很多事件,可以处理滚动条、布局、绘图等。

2.ViewGroup

ViewGroup位于android.view.ViewGroup包中,ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的。Android UI界面的一般结构如图3.1所示。

图3.1 界面结构图

可见,作为容器的ViewGroup可以包含作为叶子节点的View,也可以包含作为更低层次的子ViewGroup,而子ViewGroup又可以包含下一层的叶子节点的View和ViewGroup。Activity必须调用setContentView()方法,并传递到根节点对象的引用。Android系统接收这个参考和使用它进行测量,并绘制树。根节点的层次要求其子节点绘制自己。同时,每个树上的ViewGroup节点会负责它自己的子节点。

3.2 常用布局

在Android中几种常用的布局是:线性布局(LinearLayout)、相对布局(RelativeLayout)、帧布局(FrameLayout)、表格布局(TableLayout)及绝对布局(AbsoluteLayout)。这些布局可以调节控件在Activity中显示的大小、边距、对齐的方法等。在Android中有两种方式创建布局:一种是在项目中的layout文件夹中写XML,将各个布局写在XML中;一种是在程序中通过代码去编写,这种方式一般用得比较少,比第一种要稍微麻烦一点。本章中用的都是在XML实现,代码的实现读者可以自己去学习。

3.2.1 线性布局(LinearLayout)

顾名思义,线性布局就是将一些控件排放在一条线上,但是有水平方向和垂直方向两种。水平和垂直方向的控制由属性android:orientation来控制,这个属性有两个值:水平(Vertical)和垂直(Horizaontal),在线性布局中还有一些比较常用的属性,如android:gravity、“android:weight”等。

下面的例子将几个按钮(Button)放在几个不同方法的LinearLayout中,我们可以清楚地看到水平与垂直方向的区别。这个例子中使用了3个LinearLayout布局,最外面采用的是垂直布局,里面的两个用的是水平布局和垂直布局,效果如图3.2所示。

图3.2 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"
    android:background="#ffffff"
    >
    <LinearLayout
      android:id="@+id/LinearLayout01"
      android:layout_height="fill_parent"
      android:layout_width="fill_parent"
      android:layout_weight="1.0"
      android:orientation="horizontal"
      >
      <Button
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:text="按钮1"
            android:layout_weight="1.0"
            />
      <Button
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:text="按钮2"
            android:layout_weight="1.0"
            />
      <Button
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:text="按钮3"
            android:layout_weight="1.0"
            />
    </LinearLayout>
    <LinearLayout
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:orientation="vertical"
      android:layout_weight="1.0"
      >
      <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="按钮4"
            android:layout_weight="1.0"
            />
      <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="按钮5"
            android:layout_weight="1.0"
            />
      <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="按钮6"
            android:layout_weight="1.0"
            />
    </LinearLayout>
</LinearLayout>

在这个实例中,我们不止用到了android:orientation这个属性,还有android:layout_weight属性,此属性表示的是每个控件的权重,android:gravity属性表示的是控件的对齐方法,它的值有上(top)、下(bottom)、左(left)、右(right)4个。

3.2.2 相对布局(RelativeLayout)

相对布局是指按照控件间的相对位置进行布局,也就是说我们可以选一个控件作为参照,其他的控件可以在它的上边、下边、左边及右边等。例如,Android:layout_below属性意思是在某个控件之下,android:layout_toRightOf属性表示的是在某控件的右边,详细的布局属性请参考官方提供的PAI。

下面通过例子说明相对布局的具体用法。图3.3所示为相对布局所展现的效果,“文字B”在“文字A”的右边,“文字C”在“文字A”的下面,“文字D”在“文字B”的下面,在“文字C”的右边,具体布局文件请看下面的代码。

图3.3 相对布局

<?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:background="#ffffff"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/textView01"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="文字A"
        android:textSize="22sp"
        android:textColor="#00FF00"
        android:layout_marginLeft="20px"
        />
    <TextView
        android:id="@+id/textRight"
        android:text="文字B"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_toRightOf="@id/textView01"   //设置相对位置
        android:textColor="#FF0000"
        android:textSize="22sp"
        android:layout_marginLeft="20px"
        />
    <TextView
        android:id="@+id/text02"
        android:text="文字C"
        android:textColor="#00FFFF"
        android:textSize="22sp"
        android:layout_below="@id/textView01"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_marginLeft="20px"
        />
    <TextView
        android:id="@+id/textview02"
        android:text="文字D"
        android:layout_marginLeft="20dip"
        android:layout_below="@id/textRight"
        android:layout_toRightOf="@id/text02"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:textSize="22sp"
        android:textColor="#000000"
        />
</RelativeLayout>

对于RelativeLayout(相对布局)而言,我们主要了解控件间的相对位置,然后根据自己的要求布局控件。相对布局在界面布局中是相对用得比较多的,所以大家对其中的属性要非常了解。

3.2.3 帧布局(FrameLayout)

FrameLayout是五大布局中最简单的一个布局,在这个布局中,整个界面被当成一块空白备用区域,所有的子元素都不能被指定放置的位置,它们统统放于这块区域的左上角,并且后面的子元素直接覆盖在前面的子元素之上,将前面的子元素部分和全部遮挡。

如图3.4所示,在整个界面上使用了FrameLayout,里面嵌入了3个文本框,后面的文本框会覆盖前面的文本框。

图3.4 帧布局

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/FrameLayout01"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    >
    <TextView
        android:id="@+id/TextView01"
        android:layout_width="200px"
        android:layout_height="200px"
        android:background="@color/red"
        android:text="文本框一"
        android:textColor="#ffffff"
        >
    </TextView>
    <TextView
        android:id="@+id/TextView02"
        android:layout_width="150px"
        android:layout_height="150px"
        android:background="@color/cyan"
        android:text="@+id/TextView02" >
    </TextView>
    <TextView
        android:id="@+id/TextView03"
        android:layout_width="100px"
        android:layout_height="100px"
        android:layout_marginTop="30px"
        android:background="@color/green"
        android:paddingTop="30px" >
    </TextView>
</FrameLayout>

3.2.4 表格布局(TableLayout)

表格布局适用于NN列的布局格式。一个TableLayout由许多TableRow组成,一个TableRow就代表TableLayout中的一行。

TableRow是LinearLayout的子类,它的android:orientation属性值恒为horizontal,并且它的android:layout_width和android:layout_height属性值恒为MATCH_PARENT和WRAP_CONTENT。所以它的子元素都是横向排列并且宽高一致的。这样的设计使得每个TableRow中的子元素都相当于表格中的单元格。在TableRow中,单元格可以为空,但是不能跨列。如图3.5所示采用的就是表格布局。

图3.5 表格布局

代码如下:

<?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:background="#ffffff"
    android:stretchColumns="1" >
    <TableRow >
        <TextView
            android:layout_column="1"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Open..." />
        <TextView
            android:gravity="right"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Ctrl-O" />
    </TableRow>
    <TableRow >
        <TextView
            android:layout_column="1"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Save..." />
        <TextView
            android:gravity="right"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Ctrl-S" />
    </TableRow>
    <TableRow >
        <TextView
            android:layout_column="1"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Save As..." />
        <TextView
            android:gravity="right"
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Ctrl-Shift-S" />
    </TableRow>
    <View
        android:layout_height="2dip"
        android:background="#FF909090" />
    <TableRow >
        <TextView
            android:padding="3dip"
            android:textColor="#000000"
            android:text="X" />
        <TextView
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Import..." />
    </TableRow>
    <TableRow >
        <TextView
            android:padding="3dip"
            android:textColor="#000000"
            android:text="X" />
        <TextView
            android:padding="3dip"
            android:textColor="#000000"
            android:text="Export..." />
        <TextView
            android:gravity="right"
            android:textColor="#000000"
            android:padding="3dip"
            android:text="Ctrl-E" />
    </TableRow>
    <View
        android:layout_height="2dip"
        android:background="#FF909090" />
    <TableRow >
        <TextView
            android:layout_column="1"
            android:textColor="#000000"
            android:padding="3dip"
            android:text="Quit" />
    </TableRow>
</TableLayout>

表格布局在程序中也是用得比较多的,但是比较简单,每一行都是一个TableRow。

3.3 小结

本章主要学习了Android系统中的4种布局,还有一种布局(绝对布局)没有详细说明,就是关于x,y的定位。我们主要介绍的是相对布局、表格布局及线性布局,帧布局相对用得比较少。如果要做出漂亮的界面,需要几种布局配合使用,所以大家对每一种布局常用的属性要知道,这样在做界面时可以信手拈来。下一章将讲解的是Android中的控件。

3.4 习题

【习题1】采用线性布局(LinearLayout)实现如图exe_3.1所示的效果。

提示:参考书中的例子,本题跟例子的做法差不多,只要改一下显示的控件就行。只是此处引用了values文件下的colors.xml中的颜色资源。

图exe_3.1 线性布局的效果

【习题2】采用书中所学的相对布局(RelativeLayout)实现如图exe_3.2所示的效果。

提示:首先弄清楚这几个控件的位置,在通过属性对其进行设置。如果不明白可以查阅帮助文档,查看相应的属性。

【习题3】如图exe_3.3所示,利用表格布局实现一个简单的信息提交界面。

提示:在表格布局中,需要设置表格的行,使用TableRow。在图中每一行就是一个TableRow(这个界面的布局也可以通过相对布局来实现,有兴趣的读者可以试试)。

图exe_3.2 相对布局的效果

图exe_3.3 信息提交界面的效果