
4.3 布局管理器
在Android中,每个组件在窗体中都有具体的位置和大小,在窗体中摆放各种组件时,很难进行判断。不过,使用Android布局管理器可以很方便地控制各组件的位置和大小。Android提供了以下5种布局管理器。
相对布局管理器(RelativeLayout):通过相对定位的方式来控制组件的摆放位置。
线性布局管理器(LinearLayout):是指在垂直或水平方向上依次摆放组件。
帧布局管理器(FrameLayout):没有任何定位方式,默认情况下,所有的组件都会摆放在容器的左上角,逐个覆盖。
表格布局管理器(TableLayout):使用表格的方式按行、列来摆放组件。
绝对布局管理器(AbsoluteLayout):通过绝对定位(X、Y坐标)的方式来控制组件的摆放位置。
其中,绝对布局在Android 2.0中被标记为已过期,不过可以使用帧布局或相对布局替代。另外,在Android 4.0版本以后,又提供了一个新的布局管理器—网格布局管理器(GridLayout)。通过它可以实现跨行或跨列摆放组件。
Android提供的布局管理器均直接或间接地继承自ViewGroup,如图4.10所示。因此,所有的布局管理器都可以作为容器使用,我们可以向布局管理器中添加多个UI组件。当然,也可以将一个或多个布局管理器嵌套到其他的布局管理器中,在本章的4.3.6节中将对布局管理器的嵌套进行介绍。

图4.10 Android布局管理器的类图
4.3.1 相对布局管理器
相对布局管理器是通过相对定位的方式让组件出现在布局的任何位置。例如,图4.11所示的界面就是采用相对布局管理器来进行布局的,其中先放置组件A,然后放置组件B,让其位于组件A的下方,再放置组件C,让其位于组件A的下方,并且位于组件B的右侧。

图4.11 相对布局管理器示意图
在Android中,可以在XML布局文件中定义相对布局管理器,也可以使用Java代码来创建。推荐使用在XML布局文件中定义相对布局管理器。在XML布局文件中,定义相对布局管理器可以使用<RelativeLayout>标记,其基本的语法格式如下。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 属性列表 > </RelativeLayout>
在上面的语法中,<RelativeLayout>为起始标记;</RelativeLayout>为结束标记。在起始标记中的xmlns:android为设置XML命名空间的属性,其属性值为固定写法。
说明
在Android中,无论是创建哪一种布局管理器都有两种方法,一种是在XML布局文件中定义,另一种是使用Java代码来创建。推荐使用的是在XML布局文件中定义,所以在本书中将只介绍在XML布局文件中创建这一种方法。
RelativeLayout支持的常用XML属性如表4.3所示。
表4.3 RelativeLayout支持的常用XML属性

在相对布局管理器中,只有上面介绍的两个属性是不够的,为了更好地控制该布局管理器中各子组件的布局分布,RelativeLayout提供了一个内部类RelativeLayout.LayoutParams,通过该类提供的大量XML属性,可以很好地控制相对布局管理器中各组件的分布方式。RelativeLayout.LayoutParams支持的XML属性如表4.4所示。
表4.4 RelativeLayout.LayoutParams支持的常用XML属性

下面编写一个在程序中使用相对布局管理器的实例。
【例4.03】 软件更新提示界面(实例位置:资源包\源码\04\4.03)
在Android Studio中创建Module,名称为Software Update Tips。在该Module中实现本实例,具体步骤如下。
(1)修改新建Module的res\layout目录下的布局文件activity_main.xml,把背景图片复制到mipmap-xhdpi目录中,将默认添加的布局管理器修改为相对布局管理器(RelativeLayout),然后为其设置背景,再设置默认添加的文本框(TextView)居中显示,并且为其设置id和要显示的文字,最后在该布局管理器中,添加两个Button,并设置它们的显示位置及对齐方式,修改后的代码如下。

说明
在上面的代码中,将提示文本组件textView1设置为在屏幕中央显示,然后设置“以后再说”按钮button2在textView1的下方居右边界对齐,最后设置“现在更新”按钮button1在“以后再说”按钮的左侧显示。
(2)在工具栏中找到下拉列表框,选择要运行的应用(这里为Software Update Tips),再单击右侧的
按钮,运行效果如图4.12所示。

图4.12 软件更新提示页面
4.3.2 线性布局管理器
线性布局管理器是将放入其中的组件按照垂直或水平方向来布局,也就是控制放入其中的组件横向排列或纵向排列。其中,纵向排列的称为垂直线性布局管理器,如图4.13所示;横向排列的称为水平线性布局管理器,如图4.14所示。在垂直线性布局管理器中,每一行中只能放一个组件,而在水平线性布局管理器中,每一列中只能放一个组件。另外,Android的线性布局管理器中的组件不会换行,当组件一个挨着一个排列到窗体的边缘后,剩下的组件将不会被显示出来。
说明
在线性布局管理器中,排列方式由android:orientation属性来控制,对齐方式由android:gravity属性来控制。

图4.13 垂直线性布局管理器

图4.14 水平线性布局管理器
在XML布局文件中定义线性布局管理器,需要使用<LinearLayout>标记,其基本的语法格式如下。

1.LinearLayout的常用属性
LinearLayout支持的常用XML属性如表4.5所示。
表4.5 LinearLayout支持的常用XML属性

说明
android:layout_width和android:layout_height属性是ViewGroup.LayoutParams所支持的XML属性。对于其他的布局管理器同样适用。
注意
在水平线性布局管理器中,子组件的android:layout_width属性值通常不设置为match_parent或fill_parent,如果这样设置,在该布局管理器中一行将只能显示一个组件;在垂直线性布局管理器中,android:layout_height属性值通常不设置为match_parent或fill_parent,如果这样设置,在该布局管理器中一列将只能显示一个组件。
2.子组件在LinearLayout中的常用属性
在LinearLayout中放置的子组件,还经常用到如表4.6所示的两个属性。
表4.6 LinearLayout子组件的常用XML属性


图4.15 android:layout_weight属性示意图
注意
在线性布局管理器的定义中,使用android:layout_gravity属性设置放入其中的组件的摆放位置不起作用,要想实现这一功能,需要使用android:gravity属性。
下面编写一个在程序中使用线性布局管理器的实例。
【例4.04】 登录微信界面(实例位置:资源包\源码\04\4.04)
在Android Studio中创建Module,名称为WeChat Login。在该Module中实现本实例,具体步骤如下。
(1)修改新建Module的res\layout目录下的布局文件activity_main.xml,将默认添加的布局管理器修改为线性布局管理器LinearLayout,然后将其设置为垂直线性布局管理器。修改后的代码如下。

(2)将名称分别为zhanghao.png和mima.png的图片复制到mipmap-xxhdpi目录中,并且在线性布局管理器中添加两个EditText组件,用于输入账号和密码,然后添加一个“登录”按钮,并且在“登录”按钮下面再添加一个TextView,用来填写登录遇到的问题,关键代码如下。

说明
关于EditText(编辑框)、TextView(文本框)和Button(按钮)的详细介绍请参考第5章,这里知道这样用即可。
(3)改变默认的主题为深色ActionBar主题。打开AndroidManifest.xml文件,将其中的<application>标记的android:theme属性值@style/AppTheme修改为@style/Theme.AppCompat.Light.DarkActionBar,修改后的android:theme属性的代码如下。
android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
(4)在工具栏中找到下拉列表框,选择要运行的应用(这里为WeChat Login),再单击右侧的
按钮,运行效果如图4.16所示。

图4.16 登录微信界面
4.3.3 帧布局管理器
在帧布局管理器中,每加入一个组件都将创建一个空白的区域,通常称为一帧,默认情况下,这些帧都会被放置在屏幕的左上角,即帧布局是从屏幕的左上角(0,0)坐标点开始布局。多个组件层叠排序,后面的组件覆盖前面的组件,如图4.17所示。

图4.17 帧布局管理器
在XML布局文件中定义帧布局管理器可以使用<FrameLayout>标记,其基本的语法格式如下。

FrameLayout支持的常用XML属性如表4.7所示。
表4.7 FrameLayout支持的常用XML属性

下面编写一个在程序中使用帧布局管理器的实例。
【例4.05】 居中显示层叠的正方形(实例位置:资源包\源码\04\4.05)
在Android Studio中创建Module,名称为Frame Layout。在该Module中实现本实例,具体步骤如下。
(1)修改新建Module的res\layout目录下的布局文件activity_main.xml,将默认添加的布局代码删除,然后添加一个FrameLayout帧布局管理器,并且为其设置背景和前景图像,以及前景图像显示的位置,之后再将前景图像文件mr.png复制到mipmap-hdpi目录下,最后在该布局管理器中添加3个居中显示的TextView组件,并且为其指定不同的颜色和大小,用于更好地体现层叠效果,修改后的代码如下。

说明
帧布局管理器经常应用在游戏开发中,用于显示自定义的视图。例如,在4.2.2节的实例中,实现跟随手指的小兔子时就应用了帧布局管理器。
(2)在工具栏中找到下拉列表框,选择要运行的应用(这里为Frame Layout),再单击右侧的
按钮,运行效果如图4.18所示。

图4.18 应用帧布局管理器居中显示层叠的正方形
4.3.4 表格布局管理器
表格布局管理器与常见的表格类似,它以行、列的形式来管理放入其中的UI组件,如图4.19所示。表格布局管理器使用<TableLayout>标记定义,在表格布局管理器中,可以添加多个<TableRow>标记,每个<TableRow>标记占用一行。由于<TableRow>标记也是容器,所以在该标记中还可添加其他组件,在<TableRow>标记中,每添加一个组件,表格就会增加一列。在表格布局管理器中,列可以被隐藏;也可以被设置为伸展的,从而填充可利用的屏幕空间;还可以设置为强制收缩,直到表格匹配屏幕大小。

图4.19 表格布局管理器
说明
如果在表格布局中,直接向<TableLayout>中添加UI组件,那么这个组件将独占一行。
在XML布局文件中定义表格布局管理器的基本语法格式如下。

TableLayout继承了LinearLayout,因此它完全支持LinearLayout所支持的全部XML属性,此外,TableLayout还支持如表4.8所示的XML属性。
表4.8 TableLayout支持的XML属性

下面编写一个在程序中使用表格布局管理器的实例。
【例4.06】 喜马拉雅的用户登录界面(实例位置:资源包\源码\04\4.06)
在Android Studio中创建Module,名称为xmly Login。在该Module中实现本实例,具体步骤如下。
(1)修改新建Module的res\layout目录下的布局文件activity_main.xml,将默认添加的布局代码删除,然后添加一个TableLayout表格布局管理器,并且在该布局管理器中,添加一个背景图片,将需要的背景图片复制到mipmap-xhdpi中,然后添加4个TableRow表格行,接下来在每个表格行添加相关的图片组件,最后设置表格的第1列和第4列允许被拉伸,修改后的代码如下。


说明
在本实例中,添加了6个<TextView />,并且设置对应列允许拉伸,这是为了让登录相关组件在水平方向上居中显示而设置的。
(2)在工具栏中找到下拉列表框,选择要运行的应用(这里为Frame Layout),再单击右侧的
按钮,运行效果如图4.20所示。

图4.20 应用表格布局实现仿喜马拉雅的用户登录页面
4.3.5 网格布局管理器
网格布局管理器是在Android 4.0版本中提出的,使用GridLayout表示。在网格布局管理器中,屏幕被虚拟的细线划分成行、列和单元格,每个单元格放置一个组件,并且这个组件也可以跨行或跨列摆放,如图4.21所示。

图4.21 网格布局管理器示意图
说明
网格布局管理器与表格布局管理器有些类似,都可以以行、列的形式管理放入其中的组件,但是它们之间最大的不同就是网格布局管理器可以跨行显示组件,而表格布局管理器则不能。
在XML布局文件中,定义网格布局管理器可以使用<GridLayout>标记,其基本的语法格式如下。
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" 属性列表 > </GridLayout >
GridLayout支持的常用XML属性如表4.9所示。
表4.9 GridLayout支持的常用XML属性

为了控制网格布局管理器中各子组件的布局分布,网格布局管理器提供了GridLayout.LayoutParams内部类,在该类中提供了如表4.10所示的XML属性,用于控制网格布局管理器中各子组件的布局分布。
表4.10 GridLayout.LayoutParams支持的常用XML属性

说明
在网格布局管理器中,如果想让某个组件跨行或跨列,那么需要先通过android:layout_columnSpan或者android:layout_rowSpan设置跨越的行数或列数,然后再设置其layout_gravity属性为fill,表示该组件填满跨越的行或者列。
下面编写一个在程序中使用网格布局管理器的实例。
【例4.07】 QQ聊天信息列表界面(实例位置:资源包\源码\04\4.07)
在Android Studio中创建Module,名称为QQ Chat Message。在该Module中实现本实例,具体步骤如下。
(1)修改新建Module的res\layout目录下的布局文件activity_main.xml,将默认添加的布局管理器修改为网格布局管理器,并且将默认添加的文本框组件删除,将需要的图片复制到mipmap-mdpi目录下,然后为该网格布局管理器设置背景和列数,修改后的代码如下。

(2)添加第1行要显示的信息和头像,这里需要两个图像视图组件(ImageView),其中第1个ImageView用于显示聊天信息,占4个单元格,从第2列开始,居右放置;第2个ImageView用于显示头像,占1个单元格,位于第6列,具体代码如下。

代码注解
1 第5行代码,用于设置组件居右放置。
2 第6行代码,用于设置组件占4个单元格的位置。
3 第7行代码,用于指定组件放置在第2列。
4 第8行代码,用于指定组件放置在第1行。
5 第15行代码,用于指定组件放置在第6列。
(3)添加第2行要显示的信息和头像,这里也需要两个图像视图组件(ImageView),其中第1个ImageView用于显示头像,位于第2行的第2列;第2个ImageView用于显示聊天信息,位于第2行头像组件的下一列,具体代码如下。

(4)按照步骤(2)和步骤(3)的方法再添加两行聊天信息。
(5)在工具栏中找到下拉列表框,选择要运行的应用(这里为QQ Chat Message),再单击右侧的
按钮,运行效果如图4.22所示。

图4.22 手机QQ聊天信息列表
4.3.6 布局管理器的嵌套
在进行用户界面设计时,很多时候只通过一种布局管理器很难实现想要的界面效果,这时就得将多种布局管理器混合使用,即布局管理器的嵌套。在实现布局管理器的嵌套时,只需要记住以下几个原则即可。
根布局管理器必须包含xmlns属性。
在一个布局文件中,最多只能有一个根布局管理器。如果想要使用多个布局管理器,就需要使用一个根布局管理器将它们括起来。
不能嵌套太深。如果嵌套太深,则会影响性能,主要会降低页面的加载速度。
【例4.08】 微信朋友圈界面(实例位置:资源包\源码\04\4.08)
在Android Studio中创建Module,名称为WeChat Circle Of Friends。在该Module中实现本实例,具体步骤如下。
(1)修改新建Module的res\layout节点下的布局文件activity_main.xml,将默认添加的布局管理器修改为垂直线性布局管理器,然后将默认添加的文本框组件删除。
(2)在步骤(1)中添加的垂直线性布局管理器中,添加一个用于显示第1条朋友圈信息的相对布局管理器,然后在该布局管理器中添加一个显示头像的图像视图组件(ImageView),让它与父容器左对齐,具体代码如下。

(3)在步骤(2)中添加的相对布局管理器中,在头像ImageView组件的右侧添加3个文本框组件,分别用于显示发布人、内容和时间,具体代码如下。

(4)在上段代码的下面继续添加一个ImageView组件,用于显示评论图标,具体代码如下。

(5)在相对布局管理器的外面、线性布局管理器里面添加一个ImageView组件,用于显示一个分隔线,具体代码如下。

(6)按照步骤(2)~步骤(4)的方法再添加显示第2条朋友圈信息的代码。然后在工具栏中找到下拉列表框,选择要运行的应用(这里为WeChat Circle Of Friends),再单击右侧的
按钮,运行效果如图4.23所示。

图4.23 微信朋友圈页面