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 排按钮,最后再用剩余空间填充等号按钮。

<?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 轴都要确定方位,否则控件会出现在奇怪的位置。

<?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),创建一个个长宽为等比数列且颜色各不相同的控件,由于后加进来的控件会覆盖在前一个控件上,就会出现如图所示的效果。实现代码如下:

<?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。关于控件内容中文字间的换行,应使用 " "。

<?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列:
单独的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行 
指定到第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 的界面,可以将将计算机的按键看作一个个格子,有的按键比较大,可以使用跨行或跨列来表示。

<?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 移动应用开发》,杨谊 主编、喻德旷 副主编,人民邮电出版社

原文地址:https://www.cnblogs.com/linfangnan/p/15342118.html