详细描述下自定义 View 测量时的 MesureSpec.UNSPECIFIED

原始网页直通车


UNSPECIFIED

UNSPECIFIED :未指明的,未指定的。在这个模式下父控件不会干涉 子View 想要多大的尺寸。


这个模式什么时候会在 onMeasure 里遇到呢?

这其实取决于父容器。

拿最常用的 RecyclerView 为例,在 Item 进行 measure 时,如果列表可滚动,并且 Item 的宽或高设置了 WRAP_CONTENT 的话,那么接下来, ItemViewonMeasure 方法就会收到 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 的尺寸,但不超过指定的 MaxWidthMaxHeight , 没有内容的话就是 0。

TextView 处理 UNSPECIFIED 的方式,和 AT_MOST 是一样的。

当然了,这些尺寸都不一定等于最后 layout 出来的尺寸,因为最后决定 子View 位置和大小的,是在 onLayout 方法中,在这里你完全可以无视这些尺寸,去 layout 成自己想要的样子。不过,一般不会这么做。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值