2023年7月15日发(作者:)
对wrap_content的深⼊理解以LinearLayout为例,⼦View是⼀个⾃定义View。这样可以在onMeasure⽅法重写打印⽇志便于分析如果LinearLayout是第⼀层View,并且填满屏幕;在LinearLayout中,onMeasure接收的参数就是exactly模式;具体分析如下: @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ure(widthMeasureSpec, heightMeasureSpec); }⾼度参数heightMeasureSpec:32位整数前2位:模式,有三种情况{UNSPECIFIED, EXACTLY, AT_MOST}后30位:具体⼤⼩这样1个int值可以⽤于2种⽤途;⼯具类代码如下:int specMode = e(spec);int specSize = e(spec);其实就是位运算:public static int getMode(int measureSpec) { //noinspection ResourceType return (measureSpec & MODE_MASK); }跟踪ureprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mOrientation == VERTICAL) { measureVertical(widthMeasureSpec, heightMeasureSpec); } else { measureHorizontal(widthMeasureSpec, heightMeasureSpec); } } measureVertical() { for (int i = 0; i < count; ++i) { final LayoutParams lp = (LayoutParams) outParams();measureChildBeforeLayout(child, i, widthMeasureSpec, 0, heightMeasureSpec, usedHeight);} void measureChildBeforeLayout(View child, int childIndex, int widthMeasureSpec, int totalWidth, int heightMeasureSpec, int totalHeight) { measureChildWithMargins(child, widthMeasureSpec, totalWidth, heightMeasureSpec, totalHeight); }⼤致就是依次对每⼀个⼦View测量对于measureChildWithMargins是ViewGroup的⽅法protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { final MarginLayoutParams lp = (MarginLayoutParams) outParams(); final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight + rgin + argin + widthUsed, ); final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom + gin + Margin + heightUsed, ); e(childWidthMeasureSpec, childHeightMeasureSpec); }这⾥⽗布局测量,需要把⽗亲⾃⼰的模式和⼦控件的LayoutParam参数合并出来,结合三种⽗布局模式,算出⼦控件建议⼤⼩,建议模式,然后调⽤e public static int getChildMeasureSpec(int spec, int padding, int childDimension) { int specMode = e(spec); int specSize = e(spec); int size = (0, specSize - padding); int resultSize = 0; int resultMode = 0; switch (specMode) { // Parent has imposed an exact size on us case Y: if (childDimension >= 0) { resultSize = childDimension; resultMode = Y; } else if (childDimension == _PARENT) { // Child wants to be our size. So be it. resultSize = size; resultMode = Y; } else if (childDimension == _CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = _MOST; } break; // Parent has imposed a maximum size on us case _MOST: if (childDimension >= 0) { // Child wants a so be it resultSize = childDimension; resultMode = Y; } else if (childDimension == _PARENT) { // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; resultMode = _MOST; } else if (childDimension == _CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = _MOST; } break; case IFIED: ... break; } return asureSpec(resultSize, resultMode); }setMeasureDimension()就是设置当前view的⼤⼩ private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { mMeasuredWidth = measuredWidth; mMeasuredHeight = measuredHeight; mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; }当然不重写则是默认配置:protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }默认测量规则如下:也是根据模式来的,当然也有⼀个最⼩值,具体分析⼀下吧public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = e(measureSpec); int specSize = e(measureSpec); switch (specMode) { case IFIED: result = size; break; case _MOST: case Y: result = specSize; break; } return result; }总结:⽗布局测量的时候,会有参数宽和参数⾼,依次对⼦view测量,如果调⽤measureChildWithMargin,则根据⾃⼰本⾝的和⼦控件的LayoutParam参数共同来算出⼦控件的建议⾼度,宽度同理;具体分析,如果⼀个matchParent的linearlayout⾥⾯有⼀个wrapcontent的⼦view本⾝在linearlayout测量是Exactly则Exactly+wrapcontent=AT_MOST+⽗布局⾼度所以这时候⼦控件不重写测量⽅法⾼度默认就是和⽗布局⼀样⼤⼩
发布者:admin,转转请注明出处:http://www.yc00.com/web/1689429456a246810.html
评论列表(0条)