Android:5 个布局管理器

布局管理器#

在设计安卓的应用界面时,每个控件都需要设置具体位置和大小,通常要使用 Android 的布局管理器来设置。Android 提供了以下 5 种布局管理器:

布局管理器 功能
线性布局管理器 在垂直或水平方向上按顺序设置组件的位置
相对布局管理器 通过组件之间相互定位来确定组件的位置
帧布局管理器 没有定位方式,默认情况下所有组件摆放在左上角,逐个覆盖
表格布局管理器 将组件按照表格的行和列来放置
网格布局管理器 通过网格并可以跨行和跨列放置组件

还有一种绝对布局管理器,使用二维空间坐标来设置组件的位置,但是它在 Android 2.0 之后被废弃。

线性布局管理器#

线性布局管理器 LinearLayout将包含的组件按照垂直方向或者水平方向,按照顺序依次排列,可以是垂直方向也可以是水平方向。

xml 属性#

LinearLayout 的一些重要的 xml 属性如下。

xml 属性 说明
android:id 为当前布局管理器指定一个 ID,在 R.java 文件中会自动派生一个对应的属性
android:layout_width 设置该组件的基本宽度,可选 fill_parent、match_parent 和 wrap_content
android:layout_height 设置该组件的基本高度,可选 fill_parent、match_parent 和 wrap_content
android:orientation 设置布局管理器内组件的排列方式,horizontal 水平排列,vertical 垂直排列
android:gravity 设置布局管理器内组件的显示位置
android:background 为该组件设置背景,可以是背景图片,也可以是背景颜色

其中 fill_parent 和 match_parent 表示与父容器的宽度相同,wrap_content 组件恰好能包裹它的内容,android:gravity 其可选值包括 top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical 和 clip_horizontal。
LinearLayout 的子控件还常用到以下 xml 属性。

xml 属性 说明
android:gravity 设置组件在父容器中的位置,其可选值包括 top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical 和 clip_horizontal
android:layout_weight 设置组件所占的权重的,即设置组件占父容器剩余空间的比例。该属性的默认值为 0 表示需要显示多大的视图就占据多大的屏幕空间,当设置一个高于零的值时则将父容器的剩余空间分割

样例#

基于 LinerLayout 设计一款计算器 App 的界面,思路还是很直接的,只需要将各个按钮按顺序排列即可。主要难点在于最后 2 行分别有 2 个按钮跨了 2 行或 2 列。由于不是使用 GridLayout 布局,因此不能简单地进行排列,而是应该先放置一个 LinerLayout,然后里面再嵌套 2 个 LinerLayout 分别设置 2 排按钮,最后再用剩余空间填充等号按钮。

Copy Highlighter-hljs
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/msg" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="mc" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="m+" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="m-" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="mr" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="C" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="+/-" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="/" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="*" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="7" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="8" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="9" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="-" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="4" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="5" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="6" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="+" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="1" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="2" android:layout_weight="1" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="3" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="0px" android:layout_height="wrap_content" android:text="0" android:layout_weight="2" /> <Button android:layout_width="0px" android:layout_height="wrap_content" android:text="." android:layout_weight="1" /> </LinearLayout> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1"> <Button android:layout_width="match_parent" android:layout_height="match_parent" android:text="=" android:layout_weight="1" /> </LinearLayout> </LinearLayout> </LinearLayout>

相对布局管理器#

相对布局管理器 RelativeLayout 是通过组件之间的相对位置,来确定每个组件在界面中如何显示。

xml 属性#

RelativeLayout 支持的常用 xml 属性如下所示。

xml 属性 说明
android:gravity 设置布局管理器中各子组件的对齐方式
android:ignoreGravity 指定哪个组件不受 gravity 属性的影响

想要设置组件的相对位置,只有上面介绍的这两个属性是不够的,RelativeLayout 提供了一个内部类 RelativeLayout.LayoutParams。通过 LayoutParams 提供的大量 xml 属性,可以很好地控制相对布局管理器中各组件的分布方式。

xml 属性 说明
android:layout_above 其他 UI 组件的 ID 属性,指定该组件位于哪个组件的上方
android:layout_alignBottom 其他 UI 组件的 ID 属性,指定该组件与哪个组件的下边界对齐
android:layout_alignLeft 其他 UI 组件的 ID 属性,指定该组件与哪个组件的左边界对齐
android:layout_alignParentBottom 其他 UI 组件的 ID 属性,指定该组件是否与布局管理器底端对齐
android:layout_alignParentLeft boolean 值,指定该组件是否与布局管理器左边对齐
android:layout_alignParentRight boolean 值,指定该组件是否与布局管理器右边对齐
android:layout_alignParentTop boolean 值,指定该组件是否与布局管理器顶端对齐
android:layout_alignRight boolean 值,指定该组件与哪个组件的右边界对齐
android:layout_alignTop boolean 值,指定该组件与哪个组件的上边界对齐
android:layout_below boolean 值,指定该组件位于哪个组件的下方
android:layout_centerHorizontal boolean 值,指定该组件是否位于布局管理器水平居中的位置
android:layout_centerInParent boolean 值,指定该组件是否位于布局管理器的中央位置
android:layout_center Vertical boolean 值,指定该组件是否位于布局管理器垂直居中的位置
android:layout_toLeftOf boolean 值,指定该组件位于哪个组件的左侧
android:layout_toRightOf boolean 值,指定该组件位于哪个组件的右侧

样例#

要用 RelativeLayout 实现梅花布局,可以在页面中间填充一个空白的 TextView 作为基准,设置 4 个按钮分别相对 TextView 在上下左右四个方位即可。注意需要先进行对齐,也就是 x 轴和 y 轴都要确定方位,否则控件会出现在奇怪的位置。

Copy Highlighter-hljs
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/btn_center" android:layout_width="100dp" android:layout_height="60dp" android:layout_centerInParent="true" android:layout_centerVertical="true" /> <Button android:id="@+id/btn_top" style="@style/ButtonStyle2" android:layout_width="100dp" android:layout_height="60dp" android:layout_above="@+id/btn_center" android:layout_centerHorizontal="true" android:text="上边" /> <Button android:id="@+id/btn_bottom" style="@style/ButtonStyle2" android:layout_width="100dp" android:layout_height="60dp" android:layout_below="@+id/btn_center" android:layout_centerHorizontal="true" android:text="下边" /> <Button android:id="@+id/btn_left" style="@style/ButtonStyle2" android:layout_width="100dp" android:layout_height="60dp" android:layout_centerVertical="true" android:layout_toLeftOf="@+id/btn_center" android:text="左边" /> <Button android:id="@+id/btn_right" style="@style/ButtonStyle2" android:layout_width="100dp" android:layout_height="60dp" android:layout_centerVertical="true" android:layout_toRightOf="@+id/btn_center" android:text="右边" /> </RelativeLayout>

帧布局管理器#

帧布局管理器 FrameLayout中,每加入一个组件都会创建一个空白的区域,这个区域被称为。默认情况下这些帧会被放置在屏幕的左上角,多个组件层叠排序,后面的组件覆盖前面的组件。

xml 属性#

FrameLayout 支持的常用 xml 属性如下所示。

xml 属性 说明
android:foreground 设置帧布局管理器的前景图像
android:foregroundGravity 设置前景图像的 Gravity 属性,也就是显示的位置

样例#

利用帧布局(FrameLayout),创建一个个长宽为等比数列且颜色各不相同的控件,由于后加进来的控件会覆盖在前一个控件上,就会出现如图所示的效果。实现代码如下:

Copy Highlighter-hljs
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:width="400px" android:height="400px" android:background="#f00"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:width="340px" android:height="340px" android:background="#0f0"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:width="280px" android:height="280px" android:background="#00f"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:width="220px" android:height="220px" android:background="#ff0"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:width="160px" android:height="160px" android:background="#f0f"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:width="100px" android:height="100px" android:background="#0ff"/> </FrameLayout> </androidx.constraintlayout.widget.ConstraintLayout>

表格布局管理器#

表格布局管理器 TableLayout和 Excel 表格类似,是以行和列的性质管理放入的组件。在 TableLayout 中可以添加多个 标记,每个标记占用一行,同时 标记可以添加其他组件,每添加一个组件就会多出一列。

xml 属性#

FrameLayout 继承了 LinearLayout,因此它支持 LinearLayout 的 xml 属性,除此之外还支持常用 xml 属性如下所示。

xml 属性 说明
android:collapseColumns 设置需要被隐藏的列的列序号(从 0 开始),多个列序号之间用逗号分隔
android:shrinkColumns 设置允许被收缩的列的列序号(从 0 开始),多个列序号之间用逗号分隔
android:stretchColumns 设置允许被拉伸的列的列序号(从 0 开始),多个列序号之间用逗号分隔

一列可以同时具备 stretchColumns 及 shrinkColumns 属性,当该列的内容很多时,系统会自动调节该行的 layout height,以多行的形式显示其内容。每个单元格有如下 xml 属性。

xml 属性 说明
android:layout_column 指定该单元格在第几列显示
android:layout_span 指定该单元格占据的列数,默认为 1

样例#

在 TableLayout 中,首先列数为最多列的列数,且表格布局的子对象不能指定 layout_width 属性,永远是match_parent,不过子对象可以定义 layout_height 属性。但是根据要求宽度占满全屏,因此我们要使用属性 android:stretchColumns="0,1" ,设置可伸缩列横向扩展占满屏。指定显示在第几列要设置属性 android:layout_column,指定占据几列是设置属性
android:layout_span。关于控件内容中文字间的换行,应使用 "\n"。

Copy Highlighter-hljs
<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0,1" app:layoutDescription="@xml/activity_main_scene" tools:context=".MainActivity"> <TableRow> <TextView android:layout_margin="10dp" android:background="@color/lightgray" android:gravity="center" android:text=" 第1行 第1列" /> <TextView android:background="@color/lightgray" android:layout_margin="10dp" android:gravity="center" android:text=" 第1行 第2列 " /> </TableRow> <Button android:layout_margin="10dp" style="@style/ButtonStyle" android:text="第2行 第1列:\n单独的button,非TableRow" app:strokeColor="#BAB6B6"></Button> <TableRow> <TextView android:layout_column="1" android:layout_margin="10dp" android:background="@color/lightgray" android:gravity="center" android:text="第3行 \n指定到第2列"/> </TableRow> <TableRow> <TextView android:layout_column="0" android:layout_margin="10dp" android:background="@color/lightgray" android:gravity="center" android:text="第4行 指定到第1列" /> </TableRow> <TableRow> <TextView android:gravity="center" android:layout_span="2" android:layout_height="fill_parent" android:background="@color/lightgray" android:layout_margin="10dp" android:text="第5行 第1列 指定占据2列空间..." /> </TableRow> </TableLayout>

网格布局管理器#

网格布局管理器 GridLayout将屏幕划分为行和列的单元格,每个单元格放置一个组件。和 LinearLayout、TableLayout 不同在于,网格布局管理器跨行跨列非常方便,且整齐美观。

xml 属性#

GridLayout 支持常用 xml 属性如下所示。

xml 属性 说明
android:columnCount 指定网格的最大列数
android:orientation 当没有为放入其中的组件分配行和列时,指定其排列方式,可选 horizontal 和 vertical
android:rowCount 指定网格的最大行数
android:useDefaultMargins 指定是否使用默认的边距,其属性值设置为 true 时表示使用
android:alignmentMode 指定该布局管理器采用的对齐模式,alignBounds 对齐边界,alignMargins 对齐边距
android:rowOrderPreserved 设置行边界显示的顺序和行索引的顺序是否相同,为 true 时表示相同
android:columnOrderPreserved 设置列边界显示的顺序和列索引的顺序是否相同,为 true 时表示相同

为了控制网格布局管理器中各子组件的布局分布,网格布局管理器提供了 GridLayout.LayoutParams内部类,提供的 xml 属性如下所示。

xml 属性 说明
android:layout_column 指定该子组件位于网格的第几列
android:layout_columnSpan 指定该子组件横向跨几列,索引从 0 开始
android:layout_column Weight 指定该子组件在水平方向上的权重,即该组件分配水平剩余空间的比例
android:layout_gravity 指定该子组件采用什么方式占据该网格的空间
android:layout row 指定该子组件位于网格的第几行,索引从 0 开始
android:layout_rowSpan 指定该子组件纵向跨几行
android:layout rowWeight 指定该子组件在垂直方向上的权重,即该组件分配水平剩余空间的比例

如果想让某个组件跨行或跨列,需要先通过 android:layout columnSpan 或者 androidllayout rowSpan 设置跨越的行或列数,然后再设置其 layout gravity 属性为 fill。

样例#

基于 GridLayout 设计一款计算器 App 的界面,可以将将计算机的按键看作一个个格子,有的按键比较大,可以使用跨行或跨列来表示。

Copy Highlighter-hljs
<?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_row="7" android:columnCount="4" android:orientation="horizontal" > <EditText android:layout_columnSpan="4" android:layout_gravity="fill" android:layout_rowWeight="1" android:layout_columnWeight="1" /> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="mc"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="m+"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="m-"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="mr"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="C"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="+/-"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="/"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="*"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="7"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="8"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="9"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="-"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="4"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="5"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="6"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="+"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="1"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="2"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="3"/> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="=" android:layout_rowSpan="2" android:layout_gravity="fill" /> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="0" android:layout_columnSpan="2" android:layout_gravity="fill" /> <Button android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="."/> </GridLayout>

参考资料#

《零基础学 Android》,明日科技编著,吉林大学出版社
《Android 移动应用开发》,杨谊 主编、喻德旷 副主编,人民邮电出版社

posted @   乌漆WhiteMoon  阅读(1184)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2020-09-27 DVWA 通关指南:CSP Bypass(CSP 绕过)
点击右上角即可分享
微信分享提示
CONTENTS