标签:bre 最大值 常量 parent .net 宽高 gets comm onmeasure
在自定义控件时为了满足特定需求,widget大都是我们自己测量的。
大家都知道测量时最重要的步骤就是重写onMeasure方法,来计算出宽高。
这里面的MeasureSpec 很重要,大家也都知道,它是一个java中的静态类,它有重要的三个静态常量和三个最重要的静态方法。
我这里说下MeasureSpec 的3中模式
UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;
AT_MOST(至多),子元素至多达到指定大小的值。
看过很多博客,大家总结说,模式和XML布局有如下对应关系:
wrap_content-> MeasureSpec.AT_MOST
match_parent -> MeasureSpec.EXACTLY
50dp(确切值) -> MeasureSpec.EXACTLY
但是在具体开发中 我发现并不是一定这样,然后就看了下源码,才发现子控件的mode不只是与自身的设置有关系,它还受到父容器影响。
getChildMeasureSpec() 方法
- public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
- int specMode = MeasureSpec.getMode(spec);
- int specSize = MeasureSpec.getSize(spec);
-
- int size = Math.max(0, specSize - padding);
-
- int resultSize = 0;
- int resultMode = 0;
-
- switch (specMode) {
-
-
- case MeasureSpec.EXACTLY:
- if (childDimension >= 0) {
-
- resultSize = childDimension;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.MATCH_PARENT) {
-
-
- resultSize = size;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.WRAP_CONTENT) {
-
-
-
-
- resultSize = size;
- resultMode = MeasureSpec.AT_MOST;
- }
- break;
-
-
-
- case MeasureSpec.AT_MOST:
- if (childDimension >= 0) {
-
-
- resultSize = childDimension;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.MATCH_PARENT) {
-
-
-
-
- resultSize = size;
- resultMode = MeasureSpec.AT_MOST;
- } else if (childDimension == LayoutParams.WRAP_CONTENT) {
-
-
-
-
- resultSize = size;
- resultMode = MeasureSpec.AT_MOST;
- }
- break;
-
-
-
- case MeasureSpec.UNSPECIFIED:
- if (childDimension >= 0) {
-
-
- resultSize = childDimension;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.MATCH_PARENT) {
-
-
-
-
- resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
- resultMode = MeasureSpec.UNSPECIFIED;
- } else if (childDimension == LayoutParams.WRAP_CONTENT) {
-
-
-
-
-
- resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
- resultMode = MeasureSpec.UNSPECIFIED;
- }
- break;
- }
-
- return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
- }
总结来说 mode 取值 受父容器与子控件共同决定
父容器是MeasureSpec.EXACTLY模式
子控件是具体值, mode = MeasureSpec.EXACTLY
子控件是MATCH_PARENT, mode = MeasureSpec.EXACTLY
子控件是WRAP_CONTENT, mode = MeasureSpec.AT_MOST
父容器是MeasureSpec.AT_MOST模式
子控件是具体值, mode = MeasureSpec.EXACTLY
子控件是MATCH_PARENT, mode = MeasureSpec.AT_MOST
子控件是WRAP_CONTENT, mode = MeasureSpec.AT_MOST
父容器是MeasureSpec.UNSPECIFIED模式
子控件是具体值, mode = MeasureSpec.EXACTLY
子控件是MATCH_PARENT, mode = MeasureSpec.UNSPECIFIED
子控件是WRAP_CONTENT, mode = MeasureSpec.UNSPECIFIED
就这样
总结来说 mode 取值 受父容器与子控件共同决定
标签:bre 最大值 常量 parent .net 宽高 gets comm onmeasure
原文地址:http://www.cnblogs.com/lbsjs/p/7607169.html