1. MeasureSpec分析
1>:MeasureSpec = specSize + specMode,specSize表示大小,specMode表示规格,规格有3种:
第一:EXACTLY = 固定值(100dp)、match_parent 、fill_parent
第二:AT_MOST:wrap_content
第三:UNSPECIFIED:系统的,一般不用
2>:widthMeasureSpec 和 heightMeasureSpec这两个值,一般是 父view 计算好后传递给 子view,对于最外层根view的 这两个值,通过 performTraversals中的 getRootMeasureSpec可知:
private void performTraversals() {
// 从根布局获取 widthMeasureSpec 和 heightMeasureSpec 的值
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
}
private static int getRootMeasureSpec(int windowSize, int rootDimension) {
int measureSpec;
switch (rootDimension) {
case ViewGroup.LayoutParams.MATCH_PARENT:
// 用 MeasureSpec.makeMeasureSpec组装 MeasureSpec
// rootDimension = MATCH_PARENT,specMode就为 EXACTLY
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
break;
case ViewGroup.LayoutParams.WRAP_CONTENT:
// rootDimension = WRAP_CONTENT,specMode就为 AT_MOST
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
break;
default:
measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
break;
}
return measureSpec;
}
由上边可知:
在 getRootMeasureSpec方法中,用 MeasureSpec.makeMeasureSpec方法组装 MeasureSpec:
1>:当 rootDimension = MATCH_PARENT,specMode = EXACTLY;
2>:当 rootDimension = WRAP_CONTENT,specMode = AT_MOST;
并且 MATCH_PARENT和WRAP_CONTENT时候的 specSize都是 windowSize,表示 最外层的根view 都是 充满全屏;
2. 自定义MyView,继承View
/**
* ================================================
* Email: 2185134304@qq.com
* Created by Novate 2018/12/25 16:33
* Version 1.0
* Params:
* Description: 自定义MyView,继承View
* ================================================
*/
public class MyView extends View {
// ... 省略代码
/**
* 这里只是模拟 onMeasure方法:
* 不管在 activity_myview 布局文件中的宽高设置多少,最终的大小都是200*200;
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(200,200);
}
}
效果图如下:
![](https://img.haomeiwen.com/i5437668/a8e3c8b9d3f4250c.png)
首先调用setMeasuredDimension,然后调用 getMeasuredWidth和getMeasuredHeight 可以获取到子view 测量后的宽高;
如果直接调用 getMeasuredWidth和getMeasuredHeight ,那么这两个方法的值为0;
3. 自定义 TextView 的 onMeasure测量
比如 activity_main 布局是:LinearLayout中包裹了 3个 TextView
public class TextView extends View {
public TextView(Context context) {
this(context, null);
}
public TextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// specMode 测量模式如下
// AT_MOST = wrap_content
// EXACTLY = 固定值100dp、match_parent 、fill_parent
// 模式和大小是由父布局和自己决定的 这里所说的父布局和自己指的就是
// activity_main 中的 LinearLayout 和 TextView
//比如说:父布局是包裹内容,就算子布局是match_parent,这个时候计算出的模式还是 AT_MOST
//比如说:父布局是match_parent,子布局是match_parent,这个时候计算出的测量模式是 Exactly
// setMeasuredDimension(widthMeasureSpec , heightMeasureSpec);
}
}
网友评论