Android-LinearLayout中的layout_weight属性

前言

layout_weight 看起来像“让控件自动按比例变宽/变窄”,但真正理解它需要搞清楚:权重只是在“剩余空间”怎么分配上起作用。
下面用一个简化模型,把计算过程拆开讲清楚。

本文只讨论水平方向(横向)。

简化公式

1
实际宽度 = 基础宽度 + 剩余宽度 * (weight / weight总和)

说明(简化模型):

  • 基础宽度:参与测量时先确定出来的那部分宽度(例如固定值,或 wrap_content 测得的内容宽度;在一些场景下 layout_width="0dp" 时基础宽度为 0)。
  • 剩余宽度:容器最终可用宽度减去所有基础宽度之和。
  • weight总和:参与权重分配的子 View 的 layout_weight 之和。

示例 1:剩余空间为负(权重越大反而宽度越小)

LinearLayout 宽度为 400,内部有两个 TextViewtextView1textView2

textView1 的宽度是 match_parentlayout_weight2
textView2 的宽度是 match_parentlayout_weight3

为了说明机制,这里把基础宽度视为先测出的宽度:

  • 基础宽度:textView1 = 400textView2 = 400
  • 剩余宽度:400 - 400 - 400 = -400
  • 权重比:2/53/5

按公式计算:

  • textView1 实际宽度:400 + (-400) * (2/5) = 240
  • textView2 实际宽度:400 + (-400) * (3/5) = 160

小结:当剩余宽度为负时,表示基础宽度之和已经“超出了”容器宽度。此时 weight 也会把负剩余按比例分摊,所以 weight 越大,最终宽度反而越小。(真实项目不建议把 match_parentlayout_weight 混用,这里仅用于说明计算过程。)

示例 2:剩余空间为正(按比例分配)

LinearLayout 宽度为 400,两个 TextView 都是 wrap_content,并且测得内容宽度如下:

textView1 的内容宽度为 100layout_weight1
textView2 的内容宽度为 150layout_weight4

基础宽度之和:100 + 150 = 250
剩余宽度:400 - 250 = 150
权重比:1/54/5

按公式计算:

  • textView1 实际宽度:100 + 150 * (1/5) = 130
  • textView2 实际宽度:150 + 150 * (4/5) = 270

写出 2:3 的比例(最推荐)

如果你希望 textView1:textView2 = 2:3(即权重比为 2/53/5),最常用也最稳的写法是:让它们由 weight 决定分配空间,也就是把宽度设为 0dp

1
2
3
4
5
6
7
8
9
<TextView
android:layout_width="0dp"
android:layout_weight="2"
... />

<TextView
android:layout_width="0dp"
android:layout_weight="3"
... />

此时容器宽度由父布局确定,剩余空间就会按 2:3 分配。

常见误区

  • 如果某些子 View 不是 0dp(固定宽度或 wrap_content),weight 只负责“剩余空间”的分配,最终比例不一定严格等于 weight 的比例。
  • 想要“纯按比例分配”,优先使用 0dp + layout_weight(或竖向对应的 0dp + layout_height)。