文章目录

  • 准备工作
  • 1 LinearLayout
  • 2 RelativeLayout
  • 3 FrameLayout
  • 4 AbsoluteLayout
  • 5 TableLayout
  • 6 GridLayout
  • 7 ConstraintLayout


准备工作

Android中的布局方式有如下七种。

线性布局

<LinearLayout>

相对布局

<RelativeLayout>

帧布局

<FrameLayout>

绝对布局

<AbsoluteLayout>

表格布局

<TableLayout>

网格布局

<GridLayout>

约束布局

<ConstraintLayout>

为了演示这七种布局方式,可以新建7个fragment

按照Basic Activaty模板新建一个项目,名为layouttest。其中有两个fragment,在fragment_first.xml中插入一个LinearLayout,由于默认为约束布局,故修改其内容为

<LinearLayout
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">
</LinearLayout>

然后新建7个按钮,其id分别如下,其中button_first是其预定义的按钮,拖到LinearLayout的最下方。

<Button android:id="@+id/btn_linear_layout"/>
<Button android:id="@+id/btn_relative_layout"/>
<Button android:id="@+id/btn_frame_layout"/>
<Button android:id="@+id/btn_absolute_layout"/>
<Button android:id="@+id/btn_table_layout"/>
<Button android:id="@+id/btn_grid_layout"/>
<Button android:id="@+id/btn_constraint_layout"/>
<Button android:id="@+id/button_first"/>

每个按钮的text也做对应的更改,从而得到主页如图所示。其中NEXT为其预定义的按钮,点击之后如右图。

First Fragment

Second Fragment

android 一个布局中引入另一个布局_布局

android 一个布局中引入另一个布局_安卓_02

在左侧的com.example.layouttest中新建一个fragment:右键->New->Fragment->Fragment(Blank),命名为LinearFragment。AS除了会新建一个LinearFragment.java之外,还会在res/layout下新建一个fragment_linear.xml的布局文件。

res/navigation文件夹中有一个nav_graph.xml文件,这里存放着“导航”信息,点进去之后,新建一个fragment,用以指向LinearFragment

<fragment
    android:id="@+id/linearFragment"
    android:name="com.example.layouttest.LinearFragment"
    tools:layout="@layout/fragment_linear"/>

将视图变为split模式,连接FirstFragmentlinearFragment,则FirstFragment会添加一个action

<action
    android:id="@+id/action_FirstFragment_to_linearFragment4"
    app:destination="@id/linearFragment" />

然后再反过来连接linearFragmentFirstFragment,从而为linearFragment添加一个action

最后进入FirstFragment.java,在onViewCreated中添加

binding.btnLinearLayout.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        NavHostFragment.findNavController(FirstFragment.this)
                .navigate(R.id.action_FirstFragment_to_linearFragment);
    }
});

其中btnLinearLayout即按钮btn_linear_layoutaction_FirstFragment_to_linearFragment即导航。这样我们再启动程序,点击LinearLayout,就可以进入linearFragment了。

点击前

点击后

android 一个布局中引入另一个布局_Fragment_03

➡️

android 一个布局中引入另一个布局_安卓_04

1 LinearLayout

所谓线性布局,就是不同组块之间在单个方向存在一定的次序。可以通过orientation来规定沿水平方向还是竖直方向进行排列。

以下图为例,最外层是一个纵向的线性布局,内部又装入4个线性布局,其中前两个为横向的,后两个为纵向的。

android 一个布局中引入另一个布局_android_05

第一个线性布局为横向布局,layout_height"50dp",每个Button的长宽均为"wrap_content",所以并未完全填充这个LinearLayout

第二个线性布局也是横向布局,但每个Button代码如下

<Button
    android:layout_width="0dp"
    android:layout_weight="1"
    android:text="left"/>

即声明宽度为0的同时,分配相同的权重,所以呈现出均匀分布的特征。

第三个布局为纵向布局,其layout_width设为"match_parent",所以与屏幕等宽;layout_height设为"wrap_content",所以高度为三个按钮之和。

这三个按钮虽然纵向排布,但分别设置了layout_gravity参数,如下述代码。每个Button的宽和高均为"wrap_content",考虑到方便阅读,所以省略了。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@color/cardview_dark_background">
    <Button
        android:layout_gravity="left"
        android:text="left Top"/>

    <Button
        android:layout_gravity="center"
        android:text="center center"/>

    <Button
        android:layout_gravity="right"
        android:text="bottom"/>

</LinearLayout>

第四个也为纵向布局,但其layout_width设为"wrap_content",而layout_height设为"match_parent",所以占据了屏幕下方剩下的所有空间,但宽度却与最宽的按钮相同。

由于新建Fragment以及导航的操作比较雷同,所以后面的几种布局方式不再赘述其创建过程。

2 RelativeLayout

相对布局,就是根据其他组件的位置来确定自身位置,所以有一组最能体现“相对”定位的功能,即根据参考组件来确定自身位置。由于这些功能均可写为layout_xxx,所以在下表中省略layout

在参考组件的xx方向

对其参考组件的xx边界

对齐父组件的xx边界


above

alignTop

alignParentTop


below

alignBottom

alignParentBottom


toLeftOf

alignLeft

alignParentLeft


toRightOf

alignRight

alignParentRight

此外,还有三个重要的绝对布尔约束

  • layout_centerInParent:为True时要求该组件在容器内的正中心
  • layout_centerVertical:为True时要求该组件在容器的垂直中心
  • layout_centerHorizontal:为True时要求该组件在容器的水平中心

通过相对布局,可以轻而易举地得到下面的样式

android 一个布局中引入另一个布局_安卓_06

最中心的白色的按钮使用了layout_centerInParent,其代码为

<Button
    android:id="@+id/centerRL"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:background="@color/white"
    android:text="centerInParent"
    android:textAllCaps="false" />

四种不同颜色的按钮均参考了centerRL的位置,例如,红色按钮的代码为

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_toLeftOf="@+id/centerRL"
    android:background="#AA0000"
    android:textAllCaps="false" />

而浮在红色上面的灰色按钮则在纵向居中的同时,还与程序的左边界对齐

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_alignParentLeft="true"/>

3 FrameLayout

帧布局是最简单的布局,几乎没有任何用于排版的功能,只能通过layout_gravity来指定子控件的位置。

如下图所示,左侧的布局图可分为两个部分,分别是一个子FrameLayout,内部填充了三个按钮;在这个子Frame外同样有三个按钮,只不过声明了layout_gravity

布局图

子frame的代码

采用layout_gravity的代码

android 一个布局中引入另一个布局_java_07

android 一个布局中引入另一个布局_布局_08

android 一个布局中引入另一个布局_布局_09

4 AbsoluteLayout

绝对布局也是一种简单的布局方式,顾名思义,即根据绝对的位置坐标进行布局,正因如此,也非常简单,对于内部的控件,只需要定义4个布局参数:

  • layout_width:控件宽
  • layout_height:控件高
  • layout_x:控件左上角横坐标
  • layout_y:控件左上角纵坐标

如果用比较新的AS,那么AbsoluteLayout会被一个横线划掉,也就是说这个布局方式已经被废弃了。

之所以还要写出来,是因为这种布局方式非常符合我们的直觉。初学者往往会固执地认为应该存在这样一种布局方式然后全网找答案,所以这里很明确地讲一下:这个布局方式已经弃用了。

5 TableLayout

TableLayout更像是列表,因为其内部的每个组件都会占一整行,所有组件正好排成了一个列表。若想让TableLayout更像是个表格,那么就需要用到TableRow容器。

TableLayout中定义stretchColumns可以指定TableRow中可被拉伸的列;定义shrinkColumns可指定TableRow中可被收缩的列;定义collapseColumns可以指定被隐藏的列。

android 一个布局中引入另一个布局_Fragment_10

在上图中,最外层是一个TableLayout,里面定义了5个组件,其中

  1. 最上面独占一行的是一个按钮
  2. 绿色背景为一个TableRow
  3. 红色背景为一个带有android:stretchColumns="1"属性的Table Layout,内部封装了两个TableRow,可以看到第一列被拉伸了
  4. 黑色背景为一个带有android:shrinkColumns="1"的Layout,可以看到第一列被收缩了。
  5. 最下面的蓝色背景是隐藏了第一列的TableLayout。

6 GridLayout

此为网格布局,如果不做声明,那么网格中的控件或者按照行、或者按照列按次序排列。

如下图所示

android 一个布局中引入另一个布局_布局_11

主控件是一个GridLayout,包含了两个子控件GridLayout,分别是上面深色部分和下面浅色部分。

浅色部分写为

<GridLayout
  android:layout_width="match_parent"
  android:layout_gravity="right"
  android:columnCount="4"
  >
  <Button android:text="1"/>
  <!-- 下面直到*都是雷同的,在这里省略了 -->
  <Button android:text="0"
      android:layout_gravity="fill_horizontal"
      android:layout_columnSpan="2"/>
  <Button android:text="."/>
  <Button android:text="/"/>
</GridLayout>

GridLayout默认的方向是横向,由于声明有4列,所以当排列到第4列后会填充下一行。数字0需要横跨两行,所以有layout_columnSpan="2"

上面深色部分写为

<GridLayout
  android:layout_width="match_parent"
  android:layout_height="100dp"
  android:rowCount="3"
  android:orientation="vertical"
  android:background="#A0A0AA">
  <TextView
      android:text="0"
      android:textSize="40dp"
      android:layout_gravity="fill"
      android:layout_columnSpan="4"
      android:layout_rowSpan="2"/>
  <TextView
      android:text="0"
      android:gravity="right"
      android:layout_columnSpan="4"
      android:layout_gravity="fill_horizontal"
      />
</GridLayout>

上面的TextView横向占4格,纵向占2格,并且选择了fill;下面的则横向占4格,纵向占1格,gravity为fill_horizontal

7 ConstraintLayout

ConstraintLayout是Android中最复杂的布局方式,相比之下要比Relative更加灵活,同时占用资源更少。所以,目前也是AS默认的布局方式。

有赖于AS日益强大,ConstraintLayout可以十分方便地在设计界面进行拖动布局,例如下面的两个按钮,可以通过点击按钮四周的圆圈拉出一条约束线,将约束线的箭头放到用于约束的物体上,即可实现约束。

android 一个布局中引入另一个布局_布局_12

从代码的角度来看,约束布局和相对布局是十分相似的,但其常用方法要比相对布局更加精确。例如相对布局一般是layout_toLeftOf这种格式,即某物和另一物的位置关系;而约束布局则是layout_constraintLeft_toLeftOf,即一个组件的顶部和另一个组件的顶部对其。

由于其方法均可写为layout_constraint...,为了增加可读性,下面省略layout_constraint,列出一些常用的方法

layout_constraint

Top_toTopOf

A的顶部与B的顶部对齐

Top_toBottomOf

A的顶部与B的底部对齐

Bottom_toTopOf

A的底部与B的顶部对齐

Bottom_toBottomOf

A的底部与B的底部对齐

Left_toTopOf

A的左侧与B的顶部对

tLeft_toBottomOf

A的左侧与B的底部对齐

Left_toLeftOf

A的左边与B的左边对齐

Left_toRightOf

A的左边与B的右边对齐

Right_toTopOf

A的右对齐到B的顶部

Right_toBottomOf

A的右对齐到B的底部

Right_toLeftOf

A的右边与B的左边对

Right_toRightOf

A的右边与B的右边对

在对其之后,还可以通过layout_constraintHorizontal_biaslayout_constraintVertical_bias来设置控件的水平与垂直偏移比例。