Skip to content

Commit 5a969df

Browse files
committed
Revert two changes to LinearLayout measurement
"Include non-zero dimension views in excess space calculation" and "Always distribute excess space in LinearLayout measurement" changed LinearLayout behavior significantly in a way that wasn't covered by CTS tests. This reverts commits da2f304 and 4fabc02. Bug: 22862047 Change-Id: I8d37a525ccf295445d3239b80e5cacb10bf3c947
1 parent 5d6a2d3 commit 5a969df

1 file changed

Lines changed: 81 additions & 52 deletions

File tree

core/java/android/widget/LinearLayout.java

Lines changed: 81 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,6 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
686686
int weightedMaxWidth = 0;
687687
boolean allFillParent = true;
688688
float totalWeight = 0;
689-
int usedExcessSpace = 0;
690689

691690
final int count = getVirtualChildCount();
692691

@@ -722,23 +721,23 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
722721
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
723722

724723
totalWeight += lp.weight;
725-
726-
final boolean fillExcessSpace = lp.weight > 0;
727-
final boolean hasZeroHeight = lp.height == 0;
728-
if (heightMode == MeasureSpec.EXACTLY && fillExcessSpace && hasZeroHeight) {
724+
725+
if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) {
729726
// Optimization: don't bother measuring children who are going to use
730727
// leftover space. These views will get measured again down below if
731728
// there is any leftover space.
732729
final int totalLength = mTotalLength;
733730
mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);
734731
skippedMeasure = true;
735732
} else {
736-
if (fillExcessSpace && hasZeroHeight) {
737-
// The LinearLayout's heightMode is either UNSPECIFIED or
738-
// AT_MOST, and this child wanted to stretch to fill
739-
// available space. Translate the explicit height of 0 to
740-
// WRAP_CONTENT so that we can measure the view's ideal
741-
// height.
733+
int oldHeight = Integer.MIN_VALUE;
734+
735+
if (lp.height == 0 && lp.weight > 0) {
736+
// heightMode is either UNSPECIFIED or AT_MOST, and this
737+
// child wanted to stretch to fill available space.
738+
// Translate that to WRAP_CONTENT so that it does not end up
739+
// with a height of 0
740+
oldHeight = 0;
742741
lp.height = LayoutParams.WRAP_CONTENT;
743742
}
744743

@@ -750,16 +749,11 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
750749
child, i, widthMeasureSpec, 0, heightMeasureSpec,
751750
totalWeight == 0 ? mTotalLength : 0);
752751

753-
final int childHeight = child.getMeasuredHeight();
754-
if (fillExcessSpace) {
755-
usedExcessSpace += childHeight;
756-
757-
// Restore original layout height.
758-
if (hasZeroHeight) {
759-
lp.height = 0;
760-
}
752+
if (oldHeight != Integer.MIN_VALUE) {
753+
lp.height = oldHeight;
761754
}
762755

756+
final int childHeight = child.getMeasuredHeight();
763757
final int totalLength = mTotalLength;
764758
mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +
765759
lp.bottomMargin + getNextLocationOffset(child));
@@ -863,7 +857,7 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
863857
// Either expand children with weight to take up available space or
864858
// shrink them if they extend beyond our current bounds. If we skipped
865859
// measurement on any children, we need to measure them now.
866-
final int delta = heightSize - mTotalLength + usedExcessSpace;
860+
int delta = heightSize - mTotalLength;
867861
if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
868862
float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
869863

@@ -880,14 +874,34 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
880874

881875
float childExtra = lp.weight;
882876
if (childExtra > 0) {
883-
// Distribute excess space to child.
884-
final int childHeight = Math.max(0, (int) (childExtra * delta / weightSum));
885-
final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight,
886-
MeasureSpec.EXACTLY);
877+
// Child said it could absorb extra space -- give him his share
878+
int share = (int) (childExtra * delta / weightSum);
879+
weightSum -= childExtra;
880+
delta -= share;
881+
887882
final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
888-
mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,
889-
lp.width);
890-
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
883+
mPaddingLeft + mPaddingRight +
884+
lp.leftMargin + lp.rightMargin, lp.width);
885+
886+
// TODO: Use a field like lp.isMeasured to figure out if this
887+
// child has been previously measured
888+
if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) {
889+
// child was measured once already above...
890+
// base new measurement on stored values
891+
int childHeight = child.getMeasuredHeight() + share;
892+
if (childHeight < 0) {
893+
childHeight = 0;
894+
}
895+
896+
child.measure(childWidthMeasureSpec,
897+
MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
898+
} else {
899+
// child was skipped in the loop above.
900+
// Measure for this first time here
901+
child.measure(childWidthMeasureSpec,
902+
MeasureSpec.makeMeasureSpec(share > 0 ? share : 0,
903+
MeasureSpec.EXACTLY));
904+
}
891905

892906
// Child may now not fit in vertical dimension.
893907
childState = combineMeasuredStates(childState, child.getMeasuredState()
@@ -1003,7 +1017,6 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
10031017
int weightedMaxHeight = 0;
10041018
boolean allFillParent = true;
10051019
float totalWeight = 0;
1006-
int usedExcessSpace = 0;
10071020

10081021
final int count = getVirtualChildCount();
10091022

@@ -1053,10 +1066,8 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
10531066
child.getLayoutParams();
10541067

10551068
totalWeight += lp.weight;
1056-
1057-
final boolean fillExcessSpace = lp.weight > 0;
1058-
final boolean hasZeroWidth = lp.width == 0;
1059-
if (widthMode == MeasureSpec.EXACTLY && fillExcessSpace && hasZeroWidth) {
1069+
1070+
if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) {
10601071
// Optimization: don't bother measuring children who are going to use
10611072
// leftover space. These views will get measured again down below if
10621073
// there is any leftover space.
@@ -1083,12 +1094,14 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
10831094
skippedMeasure = true;
10841095
}
10851096
} else {
1086-
if (fillExcessSpace && hasZeroWidth) {
1087-
// The LinearLayout's widthMode is either UNSPECIFIED or
1088-
// AT_MOST, and this child wanted to stretch to fill
1089-
// available space. Translate the explicit height of 0 to
1090-
// WRAP_CONTENT so that we can measure the view's ideal
1091-
// width.
1097+
int oldWidth = Integer.MIN_VALUE;
1098+
1099+
if (lp.width == 0 && lp.weight > 0) {
1100+
// widthMode is either UNSPECIFIED or AT_MOST, and this
1101+
// child
1102+
// wanted to stretch to fill available space. Translate that to
1103+
// WRAP_CONTENT so that it does not end up with a width of 0
1104+
oldWidth = 0;
10921105
lp.width = LayoutParams.WRAP_CONTENT;
10931106
}
10941107

@@ -1100,16 +1113,11 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
11001113
totalWeight == 0 ? mTotalLength : 0,
11011114
heightMeasureSpec, 0);
11021115

1103-
final int childWidth = child.getMeasuredWidth();
1104-
if (fillExcessSpace) {
1105-
usedExcessSpace += childWidth;
1106-
1107-
// Restore the original layout width.
1108-
if (hasZeroWidth) {
1109-
lp.width = 0;
1110-
}
1116+
if (oldWidth != Integer.MIN_VALUE) {
1117+
lp.width = oldWidth;
11111118
}
11121119

1120+
final int childWidth = child.getMeasuredWidth();
11131121
if (isExactly) {
11141122
mTotalLength += childWidth + lp.leftMargin + lp.rightMargin +
11151123
getNextLocationOffset(child);
@@ -1234,7 +1242,7 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
12341242
// Either expand children with weight to take up available space or
12351243
// shrink them if they extend beyond our current bounds. If we skipped
12361244
// measurement on any children, we need to measure them now.
1237-
final int delta = widthSize - mTotalLength + usedExcessSpace;
1245+
int delta = widthSize - mTotalLength;
12381246
if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
12391247
float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
12401248

@@ -1257,13 +1265,34 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
12571265
float childExtra = lp.weight;
12581266
if (childExtra > 0) {
12591267
// Child said it could absorb extra space -- give him his share
1260-
final int childWidth = Math.max(0, (int) (childExtra * delta / weightSum));
1261-
final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth,
1262-
MeasureSpec.EXACTLY);
1263-
final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
1268+
int share = (int) (childExtra * delta / weightSum);
1269+
weightSum -= childExtra;
1270+
delta -= share;
1271+
1272+
final int childHeightMeasureSpec = getChildMeasureSpec(
1273+
heightMeasureSpec,
12641274
mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin,
12651275
lp.height);
1266-
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
1276+
1277+
// TODO: Use a field like lp.isMeasured to figure out if this
1278+
// child has been previously measured
1279+
if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) {
1280+
// child was measured once already above ... base new measurement
1281+
// on stored values
1282+
int childWidth = child.getMeasuredWidth() + share;
1283+
if (childWidth < 0) {
1284+
childWidth = 0;
1285+
}
1286+
1287+
child.measure(
1288+
MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
1289+
childHeightMeasureSpec);
1290+
} else {
1291+
// child was skipped in the loop above. Measure for this first time here
1292+
child.measure(MeasureSpec.makeMeasureSpec(
1293+
share > 0 ? share : 0, MeasureSpec.EXACTLY),
1294+
childHeightMeasureSpec);
1295+
}
12671296

12681297
// Child may now not fit in horizontal dimension.
12691298
childState = combineMeasuredStates(childState,

0 commit comments

Comments
 (0)