UI布局基础:从LinearLayout到ConstraintLayout
布局,说白了就是决定控件怎么摆。我刚开始学Android时,觉得布局就是拖拖控件完事。后来才发现,布局选得好,后面少改八遍。今天咱们就把五种核心布局捋一遍,顺便聊聊嵌套和性能那些坑。
核心观点:布局不是越复杂越好,而是越清晰越好。一个优秀的布局,读起来像一首诗,而不是一团乱麻。
一、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_alignParentBottom 和 layout_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 三步,嵌套越多越慢。
- 内存占用增加:每个布局对象都要占内存,嵌套多了内存就上去了。
- 维护困难:嵌套多了,代码读起来像迷宫,改一个地方可能影响一片。
我建议你记住几个原则:
- 能用 ConstraintLayout 就用它。一个 ConstraintLayout 能替代多层嵌套。
- 避免不必要的布局。比如一个 TextView 外面套一层 LinearLayout,完全没必要。
- 用
<merge>标签减少嵌套。这个标签可以把子布局直接合并到父布局中,少一层嵌套。 - 用
<include>复用布局。比如多个页面都用同一个标题栏,写一次,到处引用。
避坑指南:我曾经在 RecyclerView 的 item 布局里嵌套了四层布局。结果列表滑动时卡得不行。后来用 ConstraintLayout 重写,嵌套从四层降到一层,滑动流畅多了。所以,列表 item 的布局一定要扁平化,这是性能的关键。
| 布局类型 | 适用场景 | 性能 | 推荐指数 |
|---|---|---|---|
| LinearLayout | 简单线性排列 | 中等 | ⭐⭐⭐ |
| RelativeLayout | 相对定位 | 中等 | ⭐⭐⭐ |
| FrameLayout | 单层容器、Fragment | 高 | ⭐⭐⭐⭐ |
| ConstraintLayout | 复杂布局、扁平化 | 高 | ⭐⭐⭐⭐⭐ |
嗯,布局这块就聊到这儿。记住一句话:布局是 UI 的骨架,骨架搭好了,后面加功能才顺手。别贪图一时方便乱嵌套,后面改起来哭都来不及。