我之前一直想尝试将 wanandroid 的一些优质问题以各种方式推送给大家,如果大家经常看推送应该能看到:
分享 2 个 “容易误解” 的Android 知识点
给大家分享 3 个Android 问题
Android 值得深入思考面试问答分享 | 5
之前我都较为追求一次多推送几个问题,大家读起来可能也感觉比较错乱。
所以我决定做些改变,我会重新组织知识的语言结构,每次针对性讲一个问题,专注点为细节,力争讲清楚,当然要非常感谢回答问题的同学。
这个系列暂定叫:Android “易错” 知识 吧,如果阅读不景气,我再换名字,大家也可以留言,欢迎帮忙起名字。
今天来个简单的开胃一下。
这个知识点,我定义为在面试过程中答对不加分,答错扣分的题目,不过在我以前面试经历中,能完整说上来的同学不多。
我们一起来看看大家对这个知识的掌握程度吧。
在早期的博客的里面,很多时候,见到有如下的介绍:
我画圈的地方,这个值不一定是 0, 不过大多情况下 UNSPECIFIED这个模式一般不在乎这个 size。
计划每周1 篇易错系列,下期见,
拜了个拜!
推荐阅读:
善于将系统源码为己用,会“抄”也是技能!
MVC / MVP / MVVM 到底该如何选?有对错吗?
分享 2 个 “容易误解” 的Android 知识点
扫一扫
关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!
如果你的 View 设置了 match_parent,则在onMeasure 中得到的测量模式为:EXACTLY;
如果设置了 wrap_conent,则对应测量模式为:AT_MOST;
还剩下一个 UNSPECIFIED大家不用管,不常用;
- match_parent / wrap_conent一定对应 EXACTLY/ AT_MOST 吗 ?
- 测量模式到底是由哪些因素确定的?
- UNSPECIFIED 真的不常见吗?
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {int specMode = MeasureSpec.getMode(spec);
......switch (specMode) {case MeasureSpec.EXACTLY:if (childDimension >= 0) {
......
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == ViewGroup.LayoutParams.MATCH_PARENT) {
......
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == ViewGroup.LayoutParams.WRAP_CONTENT) {
......
resultMode = MeasureSpec.AT_MOST;
}break;case MeasureSpec.AT_MOST:if (childDimension >= 0) {
......
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == ViewGroup.LayoutParams.MATCH_PARENT) {
......
resultMode = MeasureSpec.AT_MOST;
} else if (childDimension == ViewGroup.LayoutParams.WRAP_CONTENT) {
......
resultMode = MeasureSpec.AT_MOST;
}break;case MeasureSpec.UNSPECIFIED:if (childDimension >= 0) {
......
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == ViewGroup.LayoutParams.MATCH_PARENT) {
......
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == ViewGroup.LayoutParams.WRAP_CONTENT) {
......
resultMode = MeasureSpec.UNSPECIFIED;
}break;
}return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}
可以看到:
在父容器的specMode为EXACTLY时,一切正常(子View尺寸指定为match_parent或精确的dimen值时,Mode = EXACTLY,尺寸指定为wrap_content则Mode = AT_MOST);
当父容器specMode为AT_MOST的时候,呵呵,可以看到,除了指定了dimen值之外,无论设置为match_parent或wrap_content,Mode最终都是会变成AT_MOST;
如果父容器specMode是UNSPECIFIED的话,跟上面的逻辑差不多,都是会变成UNSPECIFIED的,除非指定了精确的dimen值;
所以,View的onMeasure方法中收到的宽高MeasureSpec,不完全是由xml布局中设置的宽高或LayoutParams的宽高值决定的。 2. 有哪些因素影响着MeasureSpec的mode? 从刚刚的getChildMeasureSpec方法中可以看出,影响着View测量模式的因素主要是该View所属容器的测量模式。 也就是说,正常情况下(不是故意乱设置),View的测量模式是由: 它自身的LayoutParams设置的值 + 父容器的测量模式 来决定的。 为什么大家都说MeasureSpec.UNSPECIFIED不常见呢? MeasureSpec.UNSPECIFIED的相关知识: https://www.wanandroid.com/wenda/show/8613 大家都觉得这个模式不常见,很可能就是因为在编写布局时,View的宽高只能选择match_parent、wrap_content或者直接指定一个精确的尺寸,相对来说,MeasureSpec.UNSPECIFIED就显得不太透明了,因为在日常开发中,如不需定制View的话,基本上不会直接接触到。 3. MeasureSpec.UNSPECIFIED是不是真的不常见? 在日常定制View时,确实很少会专门针对这个模式去做特殊处理,大多数情况下,都会把它当成MeasureSpec.AT_MOST一样看待,就比如最最常用的TextView,它在测量时也是不会区分UNSPECIFIED和AT_MOST的。 不过,虽说这个模式比较少直接接触到,但很多场景下,我们已经在不知不觉中用上了,比如RecyclerView的Item,如果Item的宽/高是wrap_content且列表可滚动的话,那么Item的宽/高的测量模式就会是UNSPECIFIED。 还有就是NestedScrollView和ScrollView,因为它们都是扩展自FrameLayout,所以它们的子View会测量两次,第一次测量时,子View的heightMeasureSpec的模式是写死为UNSPECIFIED的。 我们在自定义ViewGroup过程中,如果允许子View的尺寸比ViewGroup大的话,在测量子View时就可以把Mode指定为UNSPECIFIED。 好了,希望这次你彻底弄明白了自定义控件的测量模式相关知识。 另外也有人给我发了个图,说这个图就能说明白了,其实这个图也有一点点小问题:![43a624df3a2c02391a572a2e2e0c9238.png](https://img-blog.csdnimg.cn/img_convert/43a624df3a2c02391a572a2e2e0c9238.png)
![3c161b8b18204699db0daed38d1e912f.png](https://img-blog.csdnimg.cn/img_convert/3c161b8b18204699db0daed38d1e912f.png)