外观
MeasureSpec 三种模式是什么?wrap_content 怎么变成具体尺寸?
标准回答
MeasureSpec 包含尺寸与模式。EXACTLY 表示父容器给定准确尺寸;AT_MOST 表示最多这么大,View 在上限内选择;UNSPECIFIED 表示本次测量在这个方向没有给出限制。
父容器综合自己的测量约束、可用空间、padding、margin 和孩子的 LayoutParams,生成孩子的 MeasureSpec。孩子再依据内容、最小尺寸和约束,得到 measuredWidth 与 measuredHeight。
因此 wrap_content 不是一种 MeasureSpec 模式,而是孩子表达的布局需求。比如内容理想宽度为 180px,父容器给 AT_MOST 120px,孩子应在约束内选择尺寸;后续文字是否换行、省略或裁剪,还取决于控件实现。match_parent 也不能脱离父容器当次测量条件,机械等同于永远 EXACTLY。
关键机制
- 测量结果包含控件自身的 padding;margin 通常由父容器在为孩子计算可用空间时处理。
- 自定义 View 的 onMeasure 需要给出结果,可借助 resolveSize / resolveSizeAndState 处理约束。
- 父容器可能对孩子测量多次;不能假设每轮遍历中 onMeasure 永远只执行一次。
通俗例子
自定义圆形控件希望内容为 80dp,加上左右 padding 后得到期望宽度,再用父容器约束裁定实际测量值。画圆时仍需适应最终内容区。
追问与回答
EXACTLY 下内容比给定尺寸大怎么办?
View 仍应遵守父容器指定的尺寸。内容如何适配由控件决定,例如 TextView 可以换行、省略或被裁剪。不能因为内容很长,就无视 EXACTLY 自行把测量宽度扩大。
易混淆点
AT_MOST 的 size 是上限,不是必须占满;UNSPECIFIED 也不是让控件返回无限大。
参考资料
内容来源
- Android 技术札记 · 原条目
measure-spec