布局基础:LinearLayout、RelativeLayout、FrameLayout、ConstraintLayout 的基本使用与属性对比

说到 Android 布局,这几乎是每个初学者第一个要啃的硬骨头。我记得刚入行那会儿,光是一个 LinearLayout 嵌套就让我折腾了一下午。后来慢慢摸透了四种核心布局的脾气,才发现布局设计其实有章可循。

今天我就把这四种布局——LinearLayout、RelativeLayout、FrameLayout、ConstraintLayout——掰开揉碎了讲。你想想看,它们各自擅长什么场景?什么时候该用谁?有哪些坑需要避开?咱们一个一个来。

一、四种布局的核心定位

先给个全景图,让你心里有个谱:

Android 四大布局核心定位 LinearLayout RelativeLayout FrameLayout ConstraintLayout 线性排列 水平/垂直 权重分配 简单直接 相对定位 兄弟/父容器 灵活但嵌套深 已逐渐淘汰 层叠覆盖 单子视图 Fragment容器 轻量高效 约束定位 扁平化结构 响应式布局 官方推荐 推荐指数:★★★☆ 推荐指数:★★☆☆ 推荐指数:★★★★ 推荐指数:★★★★★ 实际项目中常混合使用,但优先考虑 ConstraintLayout

二、LinearLayout:最朴实的线性排列

LinearLayout 就像一根绳子,把子 View 一个个串起来。要么横着串(horizontal),要么竖着串(vertical)。

我个人习惯在简单的表单布局、列表项里用它。比如登录页面的用户名和密码输入框,竖着排两行,干净利落。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="用户名" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入用户名" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录" />

</LinearLayout>
小技巧:权重(layout_weight)是 LinearLayout 的杀手锏。想让两个按钮平分屏幕宽度?给每个按钮设 weight="1" 就行。但注意,配合 0dp 使用效果最佳。

不过 LinearLayout 有个硬伤——嵌套多了性能会崩。我曾经接手过一个项目,一个界面嵌套了七八层 LinearLayout,渲染卡得不行。后来全部改成 ConstraintLayout,瞬间流畅了。

三、RelativeLayout:相对定位的老将

RelativeLayout 允许子 View 相对于父容器或其他兄弟 View 定位。比如「A 在 B 的右边」、「C 在父容器的底部居中」。这在早期 Android 开发中非常流行。

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="居中标题" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/title"
        android:layout_centerHorizontal="true"
        android:text="确定" />

</RelativeLayout>
注意:RelativeLayout 每次测量需要遍历两次子 View,性能开销比 LinearLayout 大。如果你的布局层级超过三层,我建议直接上 ConstraintLayout。

说实话,我现在已经很少用 RelativeLayout 了。为什么?因为 ConstraintLayout 能实现同样的效果,而且更扁平、更高效。但如果你在维护老项目,还是得懂它。

四、FrameLayout:轻量级的层叠容器

FrameLayout 是所有布局里最「佛系」的一个。它把所有子 View 都堆在左上角,后添加的会盖在先添加的上面。说白了,就是一个层叠容器。

它的典型应用场景:Fragment 的容器、单个图片的占位、或者做一个简单的遮罩层。

<FrameLayout
    android:layout_width="200dp"
    android:layout_height="200dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/background"
        android:scaleType="centerCrop" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center_horizontal"
        android:text="底部文字"
        android:padding="8dp" />

</FrameLayout>
核心要点:FrameLayout 的 layout_gravity 属性是唯一能控制子 View 位置的手段。想居中?设 center。想右下角?设 bottom|right。就这么简单。

我记得有一次做视频播放器,SurfaceView 和控制器 UI 就是放在 FrameLayout 里。视频画面铺满,控制按钮浮在上面,完美。

五、ConstraintLayout:现代布局的王者

ConstraintLayout 是 Google 在 2016 年推出的布局,现在已经是官方首推。它的核心思想是「约束」——每个 View 的位置由它与父容器或其他 View 之间的约束关系决定。

你想想看,以前用 RelativeLayout 实现复杂布局,往往要嵌套好几层。但 ConstraintLayout 可以用一个扁平的结构搞定一切。性能更好,维护也更方便。

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="左"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

    <Button
        android:id="@+id/btn_right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="右"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

    <Button
        android:id="@+id/btn_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="中间"
        app:layout_constraintStart_toEndOf="@id/btn_left"
        app:layout_constraintEnd_toStartOf="@id/btn_right"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
实战建议:ConstraintLayout 配合链(Chain)和屏障(Barrier)使用,能实现非常复杂的响应式布局。比如两个按钮根据内容自适应宽度,然后平分剩余空间——用链的 spread 模式一行代码搞定。

我曾经在一个电商项目中,用 ConstraintLayout 实现了商品详情页的复杂布局。图片、标题、价格、规格选择……所有元素都在一个扁平层级里,渲染速度比之前用 RelativeLayout 嵌套快了将近一倍。

六、四种布局属性对比

为了方便你查阅,我把核心属性整理成了一张表:

布局类型 核心属性 定位方式 性能 推荐场景
LinearLayout orientation, layout_weight 线性排列 中等 简单列表、表单
RelativeLayout layout_above, layout_toRightOf 相对定位 较低(两次测量) 老项目维护
FrameLayout layout_gravity 层叠覆盖 Fragment容器、遮罩
ConstraintLayout layout_constraint* 约束定位 高(扁平化) 所有复杂布局

七、避坑指南与个人经验

做布局设计这么多年,我踩过不少坑。挑几个典型的说说:

  • 嵌套过深:我曾经把一个登录界面嵌套了五层 LinearLayout,结果在低端机上卡成 PPT。后来全部改成 ConstraintLayout,一层搞定。
  • 权重滥用:LinearLayout 的权重虽然好用,但每个权重分配都会触发二次测量。如果界面里有十几个带权重的 View,性能会明显下降。
  • RelativeLayout 的测量陷阱:它需要两次遍历才能确定所有子 View 的位置。如果你的布局里用了大量相对定位,建议换成 ConstraintLayout。
  • FrameLayout 的 gravity 误区:很多人以为 FrameLayout 的子 View 会自动居中,其实默认是左上角。必须显式设置 layout_gravity 才行。
重要提醒:不要为了用 ConstraintLayout 而用。如果你的布局只有两三个 View 简单排列,LinearLayout 反而更简洁。工具要选对,不是越新越好。

嗯,布局基础就讲到这里。四种布局各有千秋,但记住一个原则:能用 ConstraintLayout 就用它,简单场景用 LinearLayout,Fragment 容器用 FrameLayout,老项目维护才考虑 RelativeLayout。这样你的布局既高效又易维护。


公众号:蓝海资料掘金营,微信deep3321