@@ -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