可以先读的文章:
https://cloud.tencent.com/developer/article/1459335
我先借用两张图:
1、
image.png2、
image.png上面两张图的由来:(前面几个判断我是加了注释了)
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
//spc 传的是(自己onMeasure方法接收到 widthMeausreSpec 和 heightMeasureSpec) 这个方法是自己测量子view的时候用的
//padding 这个参数则自己的 getPaddingLeft()和getPaddingRight() childDimension 也是子view的 layoutParmars.width 或 layoutParmars.height
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) {
// Parent has imposed an exact size on us
case MeasureSpec.EXACTLY:
if (childDimension >= 0) {
//如果 自己的mode是 exactly 并且 子View的尺寸是一个确定的值 也就是exactly 那么 子view的尺寸就是自己的 childDimension (也就像 一个线性布局 设置固定高度为 100个dp 里面再有一个TextView高度设置成
// 固定高度为 30dp 那么这个 TextView的高度就是 30个dp)
resultSize = childDimension;
//如果 自己的mode 是exactly 并且子view的 尺寸是一个具体的值并且大于0 那么 子view的 mode 就是 MeasureSpec.EXACTLY resultMode = MeasureSpec.EXACTLY;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
//子view的的 尺寸 如果 父mode 是exactly(确切的值 如 100dp ) 那么子view的 尺寸LayoutParams.MATCH_PARENT 那么 子view的尺寸就是 size 子view的尺寸是父view给自己的自己的参考尺寸
// Child wants to be our size. So be it. (孩子想成为我们的尺寸 那么给它 自己有多大就给子view多大)
resultSize = size;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break;
// Parent has imposed a maximum size on us
case MeasureSpec.AT_MOST:
if (childDimension >= 0) {
// Child wants a specific size... so be it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size, but our size is not fixed.
// Constrain child to not be bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break;
// Parent asked to see how big we want to be
case MeasureSpec.UNSPECIFIED:
if (childDimension >= 0) {
// Child wants a specific size... let him have it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size... find out how big it should
// be
resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size.... find out how
// big it should be
resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
}
break;
}
//noinspection ResourceType
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}
通过上面的方法 我们应该明天上面两张图怎么看了
这三种模式(mode)是通过 父view给我们 也就是自身的mode
image.png
通过方法然后再看图的总结是(如何看图):
如果子view是固定大小具体数值 dp/px的话,如果自身的mode是 exactly 那么 那么子view 的mode和size就是下面标红的
image.png
这个图一定要学会看如果这个图都看不懂,更不要提说自己会自定义view了
最后的总结:
一个view的measureSpc 是由自身的layoutParams和父layout的measureSpec决定的
父layout的 measureSpec 是如何获取的呢
image.png当前View获取父layout的measureSpec 只需要在当前View onMeasure() 方法里拿到 widthMeasureSpec
然后通过api MeasureSpec.getMode(widthMeasureSpec) 就可以获取了
非常不错的一篇博文:
https://www.jianshu.com/p/3b6d0c17cdb0
网友评论