布局基础:LinearLayout、RelativeLayout、FrameLayout、ConstraintLayout 的基本使用与属性对比
说到 Android 布局,这几乎是每个初学者第一个要啃的硬骨头。我记得刚入行那会儿,光是一个 LinearLayout 嵌套就让我折腾了一下午。后来慢慢摸透了四种核心布局的脾气,才发现布局设计其实有章可循。
今天我就把这四种布局——LinearLayout、RelativeLayout、FrameLayout、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>
不过 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 了。为什么?因为 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>
我记得有一次做视频播放器,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 实现了商品详情页的复杂布局。图片、标题、价格、规格选择……所有元素都在一个扁平层级里,渲染速度比之前用 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 就用它,简单场景用 LinearLayout,Fragment 容器用 FrameLayout,老项目维护才考虑 RelativeLayout。这样你的布局既高效又易维护。
公众号:蓝海资料掘金营,微信deep3321