在这里插入图片描述

布局

在 Android 开发中,布局(Layout) 是构建用户界面的基石。它决定了 UI 元素(如按钮、文本、图片等)在屏幕上的排列方式与交互行为。Android 提供了多种布局容器,每种都有其适用场景与性能特点。本文将深入讲解三种最基础且常用的布局:LinearLayout(线性布局)RelativeLayout(相对布局)FrameLayout(帧布局),并通过可视化示例帮助你直观理解其工作原理。


线性布局 LinearLayout

LinearLayout 是最简单、最常用的布局之一,它将子视图按单一方向(水平或垂直)依次排列,如同排队一样。由于其结构清晰、性能稳定,常用于表单、列表项、工具栏等场景。

布局方向

LinearLayout 通过 android:orientation 属性控制排列方向:

  • horizontal(默认):子视图从左到右水平排列;
  • vertical:子视图从上到下垂直排列。

📌 注意:若未显式设置,系统默认为 horizontal

示例:三个方块的布局对比

垂直布局(orientation="vertical"
子视图纵向堆叠,每个占据一行:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <View android:layout_width="100dp" android:layout_height="50dp" android:background="#FF5722"/>
    <View android:layout_width="100dp" android:layout_height="50dp" android:background="#4CAF50"/>
    <View android:layout_width="100dp" android:layout_height="50dp" android:background="#2196F3"/>
</LinearLayout>

效果如下:

在这里插入图片描述

水平布局(orientation="horizontal"
子视图横向并排,共享同一行:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <!-- 同上三个 View -->
</LinearLayout>

效果如下:

在这里插入图片描述

适用场景

  • 水平:顶部导航栏、底部操作按钮组;
  • 垂直:注册表单、设置项列表。

权重(Weight)

当子视图需要按比例分配剩余空间时,android:layout_weight 属性就派上用场了。它常用于实现“自适应宽度”或“等高分栏”。

工作原理:
  • 所有子视图先按 layout_width/height 分配初始空间;
  • 剩余空间按 weight 比例重新分配;
  • 通常将 layout_width 设为 0dp(水平)或 layout_height 设为 0dp(垂直),以避免计算冲突。
示例:垂直布局中的权重分配
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:orientation="vertical">
    
    <View
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#FF5722"/>
        
    <View
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:background="#4CAF50"/>
</LinearLayout>

虽然两个 Viewlayout_height 都设为 0dp,但由于权重比为 1:2,上方占 1/3 高度,下方占 2/3。

🔍 观察重点
尽管 XML 中尺寸相同,但实际渲染高度不同——这正是 weight 的作用。

在这里插入图片描述

⚠️ 性能提示
过度使用 weight 会导致 LinearLayout 多次测量(measure),影响性能。复杂布局建议改用 ConstraintLayout


对齐方式(Gravity)

android:gravity 控制子视图在父容器内的对齐方式,而 android:layout_gravity 控制当前视图在其父容器中的位置(仅在部分布局中生效,如 LinearLayout)。

常见值:
  • center:水平 + 垂直居中;
  • center_horizontal / center_vertical:仅水平或垂直居中;
  • top, bottom, left, right:靠边对齐。
示例:整体居中
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:gravity="center"
    android:background="#EEEEEE">
    <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="居中按钮"/>
</LinearLayout>

按钮将在灰色区域内完全居中

在这里插入图片描述

优先级规则:
  • 子视图的 layout_gravity 优先级高于父容器的 gravity
  • 若子视图显式设置了对齐方式,将覆盖父容器的全局设置。

例如,父容器设为 gravity="center",但某个子按钮设为 layout_gravity="top",则该按钮会靠上显示:

在这里插入图片描述


分割线(Divider)

为提升 UI 层次感,常需在列表项之间添加分割线。LinearLayout 原生支持 divider 属性,但需配合自定义 Drawable 使用。

步骤 1:创建 Shape 资源文件

res/drawable/ 目录下新建 divider_shape.xml

💡 注意:创建时需选择 “Drawable resource file” 类型。

在这里插入图片描述
在这里插入图片描述

文件内容如下(10dp 高的透明矩形,作为占位):

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@android:color/transparent"/>
    <size android:height="10dp" android:width="10dp"/>
</shape>

🎨 美化建议
color 改为 #E0E0E0 可获得浅灰色分割线,视觉效果更佳。

在这里插入图片描述
在这里插入图片描述

步骤 2:在 LinearLayout 中引用
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:divider="@drawable/divider_shape"
    android:showDividers="middle"> <!-- middle 表示仅在中间项之间显示 -->

    <TextView ... />
    <TextView ... />
    <TextView ... />
</LinearLayout>

效果如下,可见明显的间隔:

在这里插入图片描述

真机运行效果更真实:

在这里插入图片描述

优势
无需手动添加多个 View 作为分割线,代码更简洁。


相对布局 RelativeLayout

RelativeLayout 允许子视图相对于父容器或其他兄弟视图进行定位,灵活性极高,曾是复杂布局的首选(现多被 ConstraintLayout 取代)。

核心特性:
  • 通过 layout_toLeftOflayout_belowlayout_centerInParent 等属性定义位置关系;
  • 无需嵌套即可实现复杂排版,减少 View 层级;
  • 性能优于多层嵌套的 LinearLayout
示例代码解析:
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 中心主方块 -->
    <View
        android:id="@+id/box1"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="#3A3895"
        android:layout_centerInParent="true"/>

    <!-- 上方小方块:对齐 box1 顶部 & 水平居中 -->
    <View
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#CC1955"
        android:layout_above="@+id/box1"
        android:layout_centerHorizontal="true"/>

    <!-- 左侧方块:垂直居中 & 在 box1 左侧 -->
    <View
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="#36E716"
        android:layout_toStartOf="@+id/box1"
        android:layout_centerVertical="true"/>

    <!-- 右侧方块 -->
    <View
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="#E78916"
        android:layout_toEndOf="@+id/box1"
        android:layout_centerVertical="true"/>

    <!-- 下方小方块:对齐 box1 底部 & 右对齐 -->
    <View
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#8916E7"
        android:layout_below="@+id/box1"
        android:layout_alignEnd="@+id/box1"/>
</RelativeLayout>

最终效果呈“十字”分布,围绕中心方块:

在这里插入图片描述

⚠️ 局限性

  • 过度依赖 ID,ID 修改易导致布局错乱;
  • 循环依赖(A 在 B 左,B 在 A 右)会引发崩溃;
  • Google 官方已推荐使用 ConstraintLayout 替代

帧布局 FrameLayout

FrameLayout 是最简单的布局容器,所有子视图默认堆叠在左上角,后添加的视图覆盖在前一个之上。它常用于:

  • 实现叠加效果(如头像+徽章);
  • 作为 Fragment 容器;
  • 构建全屏覆盖层(如 Loading 遮罩)。
示例:同心圆效果
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="#F44336"
        android:layout_gravity="center"/>

    <View
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#E91E63"
        android:layout_gravity="center"/>

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#673AB7"
        android:layout_gravity="center"/>
</FrameLayout>

三个正方形通过 layout_gravity="center" 实现同心居中叠加,形成靶心效果:

在这里插入图片描述

性能优势
FrameLayout 测量次数最少,是性能最高的布局容器之一。


总结与选型建议

布局类型 优点 缺点 推荐场景
LinearLayout 简单直观,支持权重 嵌套深时性能差 表单、简单列表
RelativeLayout 灵活,减少嵌套 易循环依赖,维护难 已被 ConstraintLayout 取代
FrameLayout 性能极高,适合叠加 仅适合简单堆叠 Fragment 容器、遮罩层

🚀 现代开发建议

  • 新项目优先使用 ConstraintLayout(拖拽式设计 + 扁平化层级);
  • 保留 LinearLayout 用于简单线性排列;
  • FrameLayout 实现覆盖或 Fragment 容器。

掌握这三种基础布局,是迈向高效 Android UI 开发的第一步。后续可深入学习 ConstraintLayoutRecyclerView 与 Jetpack Compose,构建更现代化的应用界面。

代码部分

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    <View
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#f00"/>

    <View
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:background="#0f0"/>

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#00f"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_margin="10dp"
        >


        <View
            android:layout_width="50dp"
            android:layout_weight="1"
            android:layout_height="50dp"
            android:background="#f00"/>

        <View
            android:layout_width="70dp"
            android:layout_weight="1"
            android:layout_height="70dp"
            android:background="#0f0"/>

        <View
            android:layout_width="100dp"
            android:layout_weight="1"
            android:layout_height="100dp"
            android:background="#00f"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_margin="10dp"
        android:gravity="center"
        >

        <View
            android:layout_gravity="bottom"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#f00"/>

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#0f0"/>

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#00f"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_margin="10dp"
        android:gravity="center"
        android:divider="@drawable/line"
        android:showDividers="beginning|middle|end"
        >

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#f00"/>

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#0f0"/>

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#00f"/>

    </LinearLayout>


</LinearLayout>


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
        <View
            android:layout_margin="20dp"
            android:id="@+id/box1"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="#3A3895"
            android:layout_centerInParent="true"
       />

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#CC1955"
            android:layout_above="@+id/box1"
            android:layout_centerHorizontal="true"
            android:layout_alignStart="@+id/box1"
            />

        <View
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="#36E716"
            android:layout_toStartOf="@+id/box1"
            android:layout_centerVertical="true"
            />

        <View
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="#E78916"
            android:layout_toEndOf="@+id/box1"
            android:layout_centerVertical="true"
            />

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="#8916E7"
            android:layout_below="@+id/box1"
            android:layout_alignEnd="@+id/box1"
        />


</RelativeLayout>


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <View
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="#F44336"
        android:layout_gravity="center"/>

    <View
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#E91E63"
        android:layout_gravity="center"/>


    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#673AB7"
        android:layout_gravity="center"/>


</FrameLayout>


Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐