写了个列表项,标题 TextView 宽度设成 wrap_content,测试机上好好的,换到小屏手机文字被截成两行,右边还空一大块。布局里这几个尺寸值,含义比看上去细。

它到底怎么算宽度

wrap_content 交给父容器一句话:按内容需要的尺寸来。测量阶段控件先按自身内容算出期望宽度,父容器在剩余空间内给它。match_parent 是要占满父容器给的额度,具体 dp 是写死。三者优先级不同,混着用就容易出意外。

和 weight 一起用会打架

LinearLayout 里给子控件同时设 wrap_content 和 layout_weight,权重分配时先按测量宽度扣掉已占空间,内容长的那个会先吃掉一部分,最后比例不对。想让权重完全生效,宽度写 0dp,高度同理。这是最常见的写法错误,很多人以为是权重失效了。

ConstraintLayout 里没有 match_parent

约束布局里要填满得用 0dp 加左右约束,写 match_parent 会被当成按约束处理,效果时对时错。wrap_content 配合 constraintWidth_max 才能限制最大宽度,否则一段长文本会把整个约束撑开,旁边的控件被挤出去。

文字被截断的几个原因

  • 单行省略:要 maxLines 设 1 加 ellipsize 设 end,只写 singleLine 在新版里已废弃。
  • 父容器限宽:外面套了固定宽度的容器,里面的 wrap_content 也只能在这个范围内换行。
  • 内边距:padding 算在内容之外,文字可用宽度要减掉左右 padding。
  • 字体缩放:用户开了大字体,同一段文字测量结果变宽,正好跨过换行临界点。

什么时候别用它

列表 item 里大量 wrap_content 会触发两次测量,长列表滚动明显掉帧,能给固定高度或 0dp 就别偷懒。按钮宽度不一致时用 minWidth 统一,比逐个调 padding 靠谱。改完布局打开开发者选项里的布局边界显示,一眼能看出谁没占满。