getChildMeasureSpec
该函数的注释是:执行最难的一步:测量子View大小,测量出指定的MeasureSpec 给一个单独的子View,这个方法要计算出子View正确的HeightMeasureSpec或者WidthMeasureSpec
例如:如果一个子View知道了它自己的大小(因为它的MeasureSpec有一个EXACTLY的Mode),并且子View已经在它的LayoutParams中表明它想和父View拥有相同的大小,此时父View应该让子View去处理一个指定的大小。
传入参数
- int spec:父View的HeightMeasureSpec或者WidthMeasureSpec
- int padding:
如果是width的话:父View左右Padding+子View左右Margin+widthUsed
如果是Height的话:父View上下Padding+子View上下Margin+heightUsed
PS:其中widthUsed/heightUsed是当前LinearLayout中已经使用了的宽度/高度,所以给子View的宽度/高度就是只有父View的宽度/高度减去已经用掉了的宽度/高度,也就是剩下的高度 - int childDimension:
如果是Width的话:传入lp.width
如果是Height的话:传入lp.height
流程如下:
从父View的HeightMeasureSpec中获取specMode和specSize
算出size为Math.max(0,specSize-padding),算出来的值就是当前父View还剩的空间大小
判断父View中的SpecMode
-
如果specMode为MeasureSpec.EXACTLY:意味着父View强制设置了一个大小给子View
a) 判断childDimension>=0,如果满足,则将size设置成childDimension,Mode设置成MeasureSpec.EXACTLY,意味着如果XML中设置了具体的大小的话,那么就使用XML中具体的指定的大小b) 判断childDimension是否为LayoutParams.MATCH_PARENT,则将size设置成父View的size,Mode设置为MeasureSpec.EXACTLY,意味着建议子View的大小被强行设置成父View的大小
c) 判断childDimension是否为LayoutParams.WRAP_CONTENT,则将size设置成父View的size,Mode设置为MeasureSpec.AT_MOST,意味着让子View去处理,子View最大的大小不能超过父View
-
如果SpecMode为MeasureSpec.AT_MOST的话:意味着父View给子View一个限定的大小,子View不能超过这个大小
a) 判断childDimension>=0,如果满足,则将子View的size设置成XML中配置的大小,并且将 Mode设置成MeasureSpec.EXACTLY,意味着View的大小就是XML中设置的大小b) 如果childDimension为LayoutParams.MATCH_PARENT,则子View的大小为父View的size,但是Mode则为MeasureSpec.AT_MOST,说明希望子View的大小不要超过父View的大小
c) 如果childDimension为LayoutParams.WRAP_CONTENT,则与b)一样
-
如果SpecMode为MeasureSpec.UNSPECIFIED的话:意味着子View要多大都可以
a) 判断childDimension>=0,如果是的话,那么则将size设置成childDimension,而mode设置成MeasureSpec.EXACTLY,意味着,我可以给让你想显示多大就显示多大,但是在XML中或者addView的时候, 写死了childDimension,那么它的大小就这么大吧b) 判断childDimension为LayoutParams.MATCH_PARENT或者是LayoutParams.WRAP_CONTENT,则将size设置为0,然后mode设置为MeasureSpec.UNSPECIFIED,意味着大小让它自己决定到底要多大,随便多大都可以