UNSPECIFIED
UNSPECIFIED
:未指明的,未指定的。在这个模式下父控件不会干涉 子View
想要多大的尺寸。
这个模式什么时候会在 onMeasure 里遇到呢?
这其实取决于父容器。
拿最常用的 RecyclerView
为例,在 Item
进行 measure
时,如果列表可滚动,并且 Item
的宽或高设置了 WRAP_CONTENT
的话,那么接下来, ItemView
的 onMeasure
方法就会收到 MesureSpec.UNSPECIFIED
。
打开 RecyclerView
源码,会在 getChildMeasureSpec
方法里看到这么一句注释:
MATCH_PARENT can’t be applied since we can scroll in this dimension, wrap instead using UNSPECIFIED.
它表达的是:在可滚动的 ViewGroup
中,不应该限制 Item
的尺寸(如果是水平滚动,就不限制宽度)。为什么呢? 因为是可以滚动的,无论 Item
有多宽,有多高,通过滚动也一样能看到滚动前被遮挡的部分。
有同学可能会有疑问: 我设置了 WRAP_CONTENT
,在 onMeasure
中应该收到的是 AT_MOST
才对啊,为什么会强制变成 UNSPECIFIED
?
这是因为考虑到 Item
的尺寸有可能超出这个可滚动的 ViewGroup
的尺寸,而在 AT_MOST
模式下, 子View
的尺寸不能超出所在的 ViewGroup
的尺寸,最多只能等于。所以在这个场景下,用 UNSPECIFIED
会更合适,这个模式下你想要多大就多大。
我们在自定义 View 的时候,在测量时发现是 UNSPECIFIED 模式时,应该怎么做呢?
这个就比较自由了,既然尺寸由自己决定,那么我们既可以写死为 50,也可以写死为 200。当然了,还是要根据实际需求来定义。
比如 ImageView
,它的做法就是:有设置图片内容( drawable
)的话,会直接使用这个 drawable
的尺寸,但不超过指定的 MaxWidth
或 MaxHeight
, 没有内容的话就是 0。
而 TextView
处理 UNSPECIFIED
的方式,和 AT_MOST
是一样的。
当然了,这些尺寸都不一定等于最后 layout
出来的尺寸,因为最后决定 子View
位置和大小的,是在 onLayout
方法中,在这里你完全可以无视这些尺寸,去 layout
成自己想要的样子。不过,一般不会这么做。