UI布局基础:从LinearLayout到ConstraintLayout

布局,说白了就是决定控件怎么摆。我刚开始学Android时,觉得布局就是拖拖控件完事。后来才发现,布局选得好,后面少改八遍。今天咱们就把五种核心布局捋一遍,顺便聊聊嵌套和性能那些坑。

核心观点:布局不是越复杂越好,而是越清晰越好。一个优秀的布局,读起来像一首诗,而不是一团乱麻。

Android 布局知识体系 UI 布局基础 LinearLayout RelativeLayout FrameLayout ConstraintLayout 布局嵌套与性能 五种布局各有适用场景,选对布局事半功倍 性能优化:减少嵌套层级 → 使用 ConstraintLayout 扁平化

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

LinearLayout,顾名思义,就是让控件排成一条线。要么横着排,要么竖着排。我在项目中用得最多的就是它,简单、直观、不容易出错。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="第一行" />
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="第二行" />
    
</LinearLayout>

小技巧:android:weight 做等分布局特别方便。比如两个按钮各占一半宽度,设 layout_width="0dp" 再加 layout_weight="1" 就行。我早期不知道这个,硬写固定dp值,结果换屏就崩。

注意:LinearLayout 嵌套多了性能会下降。你想想看,每多一层嵌套,measure 和 layout 就要多走一遍。我曾经接手过一个项目,LinearLayout 套了五层,打开页面卡两秒……后来全改成了 ConstraintLayout。

二、RelativeLayout:相对定位的灵活方案

RelativeLayout 允许你指定控件相对于父容器或其他控件的位置。说白了,就是「A 在 B 的右边,C 在 A 的下方」这种关系。

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
    <Button
        android:id="@+id/btn_ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="确定" />
    
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/btn_ok"
        android:text="取消" />
    
</RelativeLayout>

我个人习惯用 RelativeLayout 做复杂表单。比如登录页,用户名输入框在密码框上面,登录按钮在密码框下面,用 RelativeLayout 几行就搞定。

避坑指南:我曾经在 RelativeLayout 里同时用了 layout_alignParentBottomlayout_above,结果两个控件叠在一起了。后来才明白,RelativeLayout 的规则是「后定义的覆盖先定义的」,顺序很重要。

三、FrameLayout:最简单的容器

FrameLayout 就像一张白纸,所有控件默认叠在左上角。你想想看,这有什么用?其实很有用——做 Fragment 容器、做加载动画的遮罩层、做悬浮按钮。

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="200dp">
    
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/bg" />
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="居中文字" />
    
</FrameLayout>

小技巧:android:layout_gravity 可以控制子控件在 FrameLayout 中的位置。比如 center 就是居中,bottom|right 就是右下角。嗯,这里要注意,gravity 和 layout_gravity 容易搞混,前者是控件内部内容的对齐,后者是控件在父容器中的对齐。

四、ConstraintLayout:现代布局的王者

ConstraintLayout 是 Google 推荐的布局方式。它用约束(constraint)来定义控件位置,说白了就是「A 的左边连 B 的右边,A 的顶部连父容器的顶部」。它的最大好处是——扁平化。一个 ConstraintLayout 能搞定以前需要三四层嵌套才能实现的效果。

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <Button
        android:id="@+id/btn_a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="A" />
    
    <Button
        android:id="@+id/btn_b"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@id/btn_a"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@id/btn_a"
        android:text="B" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

我在项目中用 ConstraintLayout 做过一个复杂的个人中心页面。以前用 RelativeLayout 嵌套 LinearLayout,光布局文件就写了 300 行。换成 ConstraintLayout 后,一个布局搞定,150 行不到。性能也好了很多。

核心优势:ConstraintLayout 支持 chain(链)、guideline(参考线)、barrier(屏障)等高级功能。比如用 chain 做等分布局,比 LinearLayout 的 weight 更灵活,而且不需要嵌套。

注意:ConstraintLayout 虽然强大,但也不是万能的。如果布局只有两三个控件,用 LinearLayout 反而更简单。别为了用而用,合适才是最好的。

五、布局嵌套与性能优化

布局嵌套,说白了就是布局套布局。比如 LinearLayout 里面套 RelativeLayout,RelativeLayout 里面再套 LinearLayout。嵌套多了会怎样?

  • 测量时间变长:每层嵌套都要走 measure、layout、draw 三步,嵌套越多越慢。
  • 内存占用增加:每个布局对象都要占内存,嵌套多了内存就上去了。
  • 维护困难:嵌套多了,代码读起来像迷宫,改一个地方可能影响一片。

我建议你记住几个原则:

  1. 能用 ConstraintLayout 就用它。一个 ConstraintLayout 能替代多层嵌套。
  2. 避免不必要的布局。比如一个 TextView 外面套一层 LinearLayout,完全没必要。
  3. <merge> 标签减少嵌套。这个标签可以把子布局直接合并到父布局中,少一层嵌套。
  4. <include> 复用布局。比如多个页面都用同一个标题栏,写一次,到处引用。

避坑指南:我曾经在 RecyclerView 的 item 布局里嵌套了四层布局。结果列表滑动时卡得不行。后来用 ConstraintLayout 重写,嵌套从四层降到一层,滑动流畅多了。所以,列表 item 的布局一定要扁平化,这是性能的关键。

布局类型 适用场景 性能 推荐指数
LinearLayout 简单线性排列 中等 ⭐⭐⭐
RelativeLayout 相对定位 中等 ⭐⭐⭐
FrameLayout 单层容器、Fragment ⭐⭐⭐⭐
ConstraintLayout 复杂布局、扁平化 ⭐⭐⭐⭐⭐

嗯,布局这块就聊到这儿。记住一句话:布局是 UI 的骨架,骨架搭好了,后面加功能才顺手。别贪图一时方便乱嵌套,后面改起来哭都来不及。

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