MeasureSpec的创建规则:
关于MeasureSpec的理解
(1) MeasureSpec基础知识
MeasureSpec通常翻译为"测量规格",它是一个32位的int数据.其中高2位代表SpecMode即某种测量模式,低30位为SpecSize代表在该模式下的规格大小.可以通过:
int specMode = MeasureSpec.getMode(measureSpec) 获取specMode
int specSize = MeasureSpec.getSize(measureSpec) 获取SpecSize
常用的SpecMode有三种:
MeasureSpec.EXACTLY
官方文档:Measure specification mode: The parent has determined an exact size for the child. The child is going to be given those bounds regardless of how big it wants to be.
父容器已经检测出子View所需要的精确大小.该子View最终的测量大小即为SpecSize.
(1) 当子View的LayoutParams的宽(高)采用具体的值(如100px)时且父容器的MeasureSpec为 MeasureSpec.EXACTLY或者.MeasureSpec.AT_MOST或者MeasureSpec.UNSPECIFIED时:系统返回给该子View的specMode就为MeasureSpec.EXACTLY.系统返回给该子View的specSize就为子View自己指定的大小(childSize)
通俗地理解:
子View的LayoutParams的宽(高)采用具体的值(如100px)时,那么说明该子View的大小是非常明确的,明确到已经用具体px值指定的地步了.那么此时不管父容器的specMode是什么,系统返回给该子View的specMode总是MeasureSpec.EXACTLY,并且系统返回给该子View的specSize就为子View自己指定的大小(childSize).
(2) 当子View的LayoutParams的宽(高)采用match_parent时并且父容器的MeasureSpec为 MeasureSpec.EXACTLY时:
系统返回给该子View的specMode就为 MeasureSpec.EXACTLY
系统返回给该子View的specSize就为该父容器剩余空间的大小(parentLeftSize)
通俗地理解:
子View的LayoutParams的宽(高)采用match_parent时并且父容器的MeasureSpec为 MeasureSpec.EXACTLY.这时候说明子View的大小还是挺明确的:就是要和父容器一样大,更加直白地说就是父容器要怎样子View就要怎样.所以,如果父容器MeasureSpec为 MeasureSpec.EXACTLY那么:系统返回给该子View的specMode就为 MeasureSpec.EXACTLY,和父容器一样.
系统返回给该子View的specSize就为该父容器剩余空间的大小(parentLeftSize),就是父容器的剩余大小.同样的道理如果此时,MeasureSpec为 MeasureSpec.AT_MOST呢?系统返回给该子View的specMode也为 MeasureSpec.AT_MOST,和父容器一样.
系统返回给该子View的specSize也为该父容器剩余空间的大小(parentLeftSize),就是父容器的剩余大小.
MeasureSpec.AT_MOST
官方文档 The child can be as large as it wants up to the specified size.
父容器指定了一个可用大小即specSize,子View的大小不能超过该值.
(1) 当子View的LayoutParams的宽(高)采用match_parent时并且父容器的MeasureSpec为 MeasureSpec.AT_MOST时:
系统返回给该子View的specMode就为 MeasureSpec.AT_MOST
系统返回给该子View的specSize就为该父容器剩余空间的大小(parentLeftSize)
这种情况已经在上面介绍 MeasureSpec.EXACTLY时已经讨论过了.
(2) 当子View的LayoutParams的宽(高)采用wrap_content时并且父容器的MeasureSpec为 MeasureSpec.EXACTLY时:
系统返回给该子View的specMode就为 MeasureSpec.AT_MOST
系统返回给该子View的specSize就为该父容器剩余空间的大小(parentLeftSize)
通俗地理解:
子View的LayoutParams的宽(高)采用wrap_content时说明这个子View的宽高不明确,要视content而定.
这个时候如果父容器的MeasureSpec为 MeasureSpec.EXACTLY即父容器是一个精确模式;这个时候简单地说
子View是不确定的,父容器是确定的,那么
系统返回给该子View的specMode也就是不确定的即为 MeasureSpec.AT_MOST
系统返回给该子View的specSize就为该父容器剩余空间的大小(parentLeftSize)
(3) 当子View的LayoutParams的宽(高)采用wrap_content时并且父容器的MeasureSpec为 MeasureSpec.AT_MOST时:
系统返回给该子View的specMode就为 MeasureSpec.AT_MOST
系统返回给该子View的specSize就为该父容器剩余空间的大小(parentLeftSize)
通俗地理解:
子View的LayoutParams的宽(高)采用wrap_content时说明这个子View的宽高不明确,要视content而定.
这个时候如果父容器的MeasureSpec为 MeasureSpec.AT_MOST这个时候简单地说
子View是不确定的,父容器也是不确定的,那么系统返回给该子View的specMode也就是不确定的即为 MeasureSpec.AT_MOST
系统返回给该子View的specSize就为该父容器剩余空间的大小(parentLeftSize)
MeasureSpec.UNSPECIFIED
官方文档 The parent has not imposed any constraint on the child. It can be whatever size it wants.
父容器不对子View的大小做限制. 一般用作Android系统内部,或者ListView和ScrollView.在此不做讨论.
关于这个三种测量规格下面的源码分析中体现得很明显,也可参考以下附图.
(2) 在onMeasure()时子View的MeasureSpec的形成过程分析关于该技术点的讨论,请看下面的源码分析.