登录

去注册

登录

注册

去登录

注册

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

xiaoyang   2019-06-20   收藏

相信大家多数都能说出自定义的步骤,但是很多细节上的问题其实也需要关注。


针对:


MesureSpec.UNSPECIFIED


1. 这个模式什么时候会遇到?

2. 遇到后怎么处理?

3. 有什么注意事项?


以后问答每周 2-3 问,没有人回答会挂稍微久一些,希望大家踊跃参与。




16

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模式下,你的尺寸不能超出你所在的ViewGroup的尺寸,最多只能等于。所以用UNSPECIFIED会更合适,这个模式下你想要多大就多大。

那么,我们在自定义View的时候,在测量时发现是UNSPECIFIED模式时,应该怎么做呢:

这个就比较自由了,既然尺寸由自己决定,那么我可以写死为50,也可以固定为200。
但还是建议结合实际需求来定义咯。
比如ImageView,它的做法就是:有设置图片内容(drawable)的话,会直接使用这个drawable的尺寸,但不会超过指定的MaxWidth或MaxHeight, 没有内容的话就是0。
而TextView处理UNSPECIFIED的方式,和AT_MOST是一样的。

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



回复
鸿洋 : @陈小缘 

等你好久咯~

2019-06-19 回复
nanchen2251 : @陈小缘 

上面的解答非常棒。给个赞

2019-06-18 回复
0

小缘同学牛批(破音

回复

删除留言

确认删除留言,会导致相关评论丢失?

取消 确定