下面列出了android.view.View#resolveSizeAndState ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Set this FlexboxLayouts' width and height depending on the calculated size of main axis and
* cross axis.
*
* @param flexDirection the value of the flex direction
* @param widthMeasureSpec horizontal space requirements as imposed by the parent
* @param heightMeasureSpec vertical space requirements as imposed by the parent
* @param childState the child state of the View
* @see #getFlexDirection()
* @see #setFlexDirection(int)
*/
private void setMeasuredDimensionForFlex(@FlexDirection int flexDirection, int widthMeasureSpec,
int heightMeasureSpec, int childState) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int calculatedMaxHeight;
int calculatedMaxWidth;
switch (flexDirection) {
case FlexDirection.ROW: // Intentional fall through
case FlexDirection.ROW_REVERSE:
calculatedMaxHeight = getSumOfCrossSize() + getPaddingTop()
+ getPaddingBottom();
calculatedMaxWidth = getLargestMainSize();
break;
case FlexDirection.COLUMN: // Intentional fall through
case FlexDirection.COLUMN_REVERSE:
calculatedMaxHeight = getLargestMainSize();
calculatedMaxWidth = getSumOfCrossSize() + getPaddingLeft() + getPaddingRight();
break;
default:
throw new IllegalArgumentException("Invalid flex direction: " + flexDirection);
}
int widthSizeAndState;
switch (widthMode) {
case MeasureSpec.EXACTLY:
if (widthSize < calculatedMaxWidth) {
childState = View
.combineMeasuredStates(childState, View.MEASURED_STATE_TOO_SMALL);
}
widthSizeAndState = View.resolveSizeAndState(widthSize, widthMeasureSpec,
childState);
break;
case MeasureSpec.AT_MOST: {
if (widthSize < calculatedMaxWidth) {
childState = View
.combineMeasuredStates(childState, View.MEASURED_STATE_TOO_SMALL);
} else {
widthSize = calculatedMaxWidth;
}
widthSizeAndState = View.resolveSizeAndState(widthSize, widthMeasureSpec,
childState);
break;
}
case MeasureSpec.UNSPECIFIED: {
widthSizeAndState = View
.resolveSizeAndState(calculatedMaxWidth, widthMeasureSpec, childState);
break;
}
default:
throw new IllegalStateException("Unknown width mode is set: " + widthMode);
}
int heightSizeAndState;
switch (heightMode) {
case MeasureSpec.EXACTLY:
if (heightSize < calculatedMaxHeight) {
childState = View.combineMeasuredStates(childState,
View.MEASURED_STATE_TOO_SMALL
>> View.MEASURED_HEIGHT_STATE_SHIFT);
}
heightSizeAndState = View.resolveSizeAndState(heightSize, heightMeasureSpec,
childState);
break;
case MeasureSpec.AT_MOST: {
if (heightSize < calculatedMaxHeight) {
childState = View.combineMeasuredStates(childState,
View.MEASURED_STATE_TOO_SMALL
>> View.MEASURED_HEIGHT_STATE_SHIFT);
} else {
heightSize = calculatedMaxHeight;
}
heightSizeAndState = View.resolveSizeAndState(heightSize, heightMeasureSpec,
childState);
break;
}
case MeasureSpec.UNSPECIFIED: {
heightSizeAndState = View.resolveSizeAndState(calculatedMaxHeight,
heightMeasureSpec, childState);
break;
}
default:
throw new IllegalStateException("Unknown height mode is set: " + heightMode);
}
setMeasuredDimension(widthSizeAndState, heightSizeAndState);
}
@Override
public int resolveSizeAndState(int size, int measureSpec, int state) {
return View.resolveSizeAndState(size, measureSpec, state);
}
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
return View.resolveSizeAndState(size, measureSpec, childMeasuredState);
}
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
return View.resolveSizeAndState(size, measureSpec, childMeasuredState);
}
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
return View.resolveSizeAndState(size, measureSpec, childMeasuredState);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
// General goal: Adjust dimensions to maintain the requested aspect ratio as much
// as possible. Depending on the measure specs handed down, this may not be possible
// Only set one of these to true
boolean scaleWidth = false;
boolean scaleHeight = false;
// Sort out which dimension to scale, if either can be. There are 9 combinations of
// possible measure specs; a few cases below handle multiple combinations
//noinspection StatementWithEmptyBody
if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
// Can't adjust sizes at all, do nothing
} else if (widthMode == MeasureSpec.EXACTLY) {
// Width is fixed, heightMode either AT_MOST or UNSPECIFIED, so adjust height
scaleHeight = true;
} else if (heightMode == MeasureSpec.EXACTLY) {
// Height is fixed, widthMode either AT_MOST or UNSPECIFIED, so adjust width
scaleWidth = true;
} else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
// Need to fit into box <= [width, height] in size.
// Maximize the View's area while maintaining aspect ratio
// This means keeping one dimension as large as possible and shrinking the other
float boxAspectRatio = width / (float) height;
if (boxAspectRatio > mAspectRatio) {
// Box is wider than requested aspect; pillarbox
scaleWidth = true;
} else {
// Box is narrower than requested aspect; letterbox
scaleHeight = true;
}
} else if (widthMode == MeasureSpec.AT_MOST) {
// Maximize width, heightSpec is UNSPECIFIED
scaleHeight = true;
} else if (heightMode == MeasureSpec.AT_MOST) {
// Maximize height, widthSpec is UNSPECIFIED
scaleWidth = true;
} else {
// Both MeasureSpecs are UNSPECIFIED. This is probably a pathological layout,
// with width == height == 0
// but arbitrarily scale height anyway
scaleHeight = true;
}
// Do the scaling
if (scaleWidth) {
width = (int) (height * mAspectRatio);
} else if (scaleHeight) {
height = (int) (width / mAspectRatio);
}
// Override width/height if needed for EXACTLY and AT_MOST specs
width = View.resolveSizeAndState(width, widthMeasureSpec, 0);
height = View.resolveSizeAndState(height, heightMeasureSpec, 0);
// Finally set the calculated dimensions
setMeasuredDimension(width, height);
}
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
return View.resolveSizeAndState(size, measureSpec, childMeasuredState);
}