您的位置:首页 > 其它

自定义ViewGroup应如何去使用setMeasuredDimsion(int,int)和计算其参数

2016-11-16 23:10 483 查看
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
boolean optical = isLayoutModeOptical(this);
if (optical != isLayoutModeOptical(mParent)) {
Insets insets = getOpticalInsets();
int opticalWidth  = insets.left + insets.right;
int opticalHeight = insets.top  + insets.bottom;

measuredWidth  += optical ? opticalWidth  : -opticalWidth;
measuredHeight += optical ? opticalHeight : -opticalHeight;
}
setMeasuredDimensionRaw(measuredWidth, measuredHeight);
}
private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;

mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}

从上面两个方法可以看出,setMeasuredDemension其实是设置了view#measuredWidth和measureHeight。这个两个成员是复型变量,和measureSpec类似,就是其0-30位是表示尺寸,最高位表示是否TOO_SMALL。所以在设置这两个变量之前,要在原来的测量值的基础上先判断是否太小(相比于控件期望的值),若是,则在原来测量值的基础上加上TOO_SMALL标志。可以用下面的方法得到这个复型值:View#resolveSizeAndState()

/**
* Utility to reconcile a desired size and state, with constraints imposed
* by a MeasureSpec. Will take the desired size, unless a different size
* is imposed by the constraints. The returned value is a compound integer,
* with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
* optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
* resulting size is smaller than the size the view wants to be.
*
* @param size How big the view wants to be.
* @param measureSpec Constraints imposed by the parent.
* @param childMeasuredState Size information bit mask for the view's
* children.
* @return Size information bit mask as defined by
* {@link #MEASURED_SIZE_MASK} and
* {@link #MEASURED_STATE_TOO_SMALL}.
*/
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec);
final int result;
switch (specMode) {
case MeasureSpec.AT_MOST:
if (specSize < size) {
result = specSize | MEASURED_STATE_TOO_SMALL;
} else {
result = size;
}
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
case MeasureSpec.UNSPECIFIED:
default:
result = size;
}
return result | (childMeasuredState & MEASURED_STATE_MASK);
}

其中参数size为控件期望值(与测量值不一样),在SpecMode为AT_MOST时若期望值小于SpecSize(此时必为parentSize),则返回带有不满意标志的值,值大小为SpecSize(即parentSize)。SpecMode为EXACTLY时值为SpecSize,但不添加不满意标志。
上面的方法中还还有一个childMeasuredState参数,表示child对尺寸是否满意,如果该值的最高位为1,则表示不满意。则无论ViewGroup的SpecMode是什么都需要在返回结果中添加不满意标记。

注意:因为成员变量measuredWidth/Height是个复型变量,所以在获取宽高时,要使用getMeasuredWidth()方法,而不能直接使用这个参数,也不能用getMeasureWidthAndState()这方法(该方法用于获取成员变量measuredWidth)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐