@@ -850,32 +850,65 @@ final boolean isGone(View c) {
850850 return c .getVisibility () == View .GONE ;
851851 }
852852
853- private void measureChildWithMargins (View child , int widthMeasureSpec , int heightMeasureSpec ) {
854- LayoutParams lp = getLayoutParams ( child );
855- int childWidthMeasureSpec = getChildMeasureSpec (widthMeasureSpec ,
856- mPaddingLeft + mPaddingRight + getTotalMargin (child , true ), lp . width );
857- int childHeightMeasureSpec = getChildMeasureSpec (heightMeasureSpec ,
858- mPaddingTop + mPaddingBottom + getTotalMargin (child , false ), lp . height );
859- child .measure (childWidthMeasureSpec , childHeightMeasureSpec );
853+ private void measureChildWithMargins2 (View child , int parentWidthSpec , int parentHeightSpec ,
854+ int childWidth , int childHeight ) {
855+ int childWidthSpec = getChildMeasureSpec (parentWidthSpec ,
856+ mPaddingLeft + mPaddingRight + getTotalMargin (child , true ), childWidth );
857+ int childHeightSpec = getChildMeasureSpec (parentHeightSpec ,
858+ mPaddingTop + mPaddingBottom + getTotalMargin (child , false ), childHeight );
859+ child .measure (childWidthSpec , childHeightSpec );
860860 }
861861
862- private void measureChildrenWithMargins (int widthMeasureSpec , int heightMeasureSpec ) {
862+ private void measureChildrenWithMargins (int widthSpec , int heightSpec , boolean firstPass ) {
863863 for (int i = 0 , N = getChildCount (); i < N ; i ++) {
864864 View c = getChildAt (i );
865865 if (isGone (c )) continue ;
866- measureChildWithMargins (c , widthMeasureSpec , heightMeasureSpec );
866+ LayoutParams lp = getLayoutParams (c );
867+ if (firstPass ) {
868+ measureChildWithMargins2 (c , widthSpec , heightSpec , lp .width , lp .height );
869+ } else {
870+ Spec spec = (orientation == HORIZONTAL ) ? lp .columnSpec : lp .rowSpec ;
871+ if (spec .alignment == FILL ) {
872+ Interval span = spec .span ;
873+ Axis axis = (orientation == HORIZONTAL ) ? horizontalAxis : verticalAxis ;
874+ int [] locations = axis .getLocations ();
875+ int size = locations [span .max ] - locations [span .min ];
876+ if (orientation == HORIZONTAL ) {
877+ measureChildWithMargins2 (c , widthSpec , heightSpec , size , lp .height );
878+ } else {
879+ measureChildWithMargins2 (c , widthSpec , heightSpec , lp .width , size );
880+ }
881+ }
882+ }
867883 }
868884 }
869885
870886 @ Override
871887 protected void onMeasure (int widthSpec , int heightSpec ) {
872- measureChildrenWithMargins (widthSpec , heightSpec );
888+ /** If we have been called by {@link View#measure(int, int)}, one of width or height
889+ * is likely to have changed. We must invalidate if so. */
890+ invalidateValues ();
891+
892+ measureChildrenWithMargins (widthSpec , heightSpec , true );
893+
894+ int width , height ;
895+
896+ // Use the orientation property to decide which axis should be laid out first.
897+ if (orientation == HORIZONTAL ) {
898+ width = horizontalAxis .getMeasure (widthSpec );
899+ measureChildrenWithMargins (widthSpec , heightSpec , false );
900+ height = verticalAxis .getMeasure (heightSpec );
901+ } else {
902+ height = verticalAxis .getMeasure (heightSpec );
903+ measureChildrenWithMargins (widthSpec , heightSpec , false );
904+ width = horizontalAxis .getMeasure (widthSpec );
905+ }
873906
874- int width = getPaddingLeft () + horizontalAxis . getMeasure ( widthSpec ) + getPaddingRight ();
875- int height = getPaddingTop () + verticalAxis . getMeasure ( heightSpec ) + getPaddingBottom ();
907+ int hPadding = getPaddingLeft () + getPaddingRight ();
908+ int vPadding = getPaddingTop () + getPaddingBottom ();
876909
877- int measuredWidth = Math .max (width , getSuggestedMinimumWidth ());
878- int measuredHeight = Math .max (height , getSuggestedMinimumHeight ());
910+ int measuredWidth = Math .max (hPadding + width , getSuggestedMinimumWidth ());
911+ int measuredHeight = Math .max (vPadding + height , getSuggestedMinimumHeight ());
879912
880913 setMeasuredDimension (
881914 resolveSizeAndState (measuredWidth , widthSpec , 0 ),
@@ -1015,16 +1048,14 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
10151048 for the vertical one.
10161049 */
10171050 final class Axis {
1018- private static final int MIN_VALUE = -1000000 ;
1019-
10201051 private static final int NEW = 0 ;
10211052 private static final int PENDING = 1 ;
10221053 private static final int COMPLETE = 2 ;
10231054
10241055 public final boolean horizontal ;
10251056
10261057 public int definedCount = UNDEFINED ;
1027- private int inferredCount = UNDEFINED ;
1058+ private int maxIndex = UNDEFINED ;
10281059
10291060 PackedMap <Spec , Bounds > groupBounds ;
10301061 public boolean groupBoundsValid = false ;
@@ -1056,28 +1087,29 @@ private Axis(boolean horizontal) {
10561087 this .horizontal = horizontal ;
10571088 }
10581089
1059- private int maxIndex () {
1060- // note the number Integer.MIN_VALUE + 1 comes up in undefined cells
1061- int count = -1 ;
1090+ private int calculateMaxIndex () {
1091+ // the number Integer.MIN_VALUE + 1 comes up in undefined cells
1092+ int result = -1 ;
10621093 for (int i = 0 , N = getChildCount (); i < N ; i ++) {
10631094 View c = getChildAt (i );
10641095 LayoutParams params = getLayoutParams (c );
10651096 Spec spec = horizontal ? params .columnSpec : params .rowSpec ;
1066- count = max (count , spec .span .min );
1067- count = max (count , spec .span .max );
1097+ Interval span = spec .span ;
1098+ result = max (result , span .min );
1099+ result = max (result , span .max );
10681100 }
1069- return count == -1 ? UNDEFINED : count ;
1101+ return result == -1 ? UNDEFINED : result ;
10701102 }
10711103
1072- private int getInferredCount () {
1073- if (inferredCount == UNDEFINED ) {
1074- inferredCount = max (0 , maxIndex ()); // if there are no cells, actual count is zero
1104+ private int getMaxIndex () {
1105+ if (maxIndex == UNDEFINED ) {
1106+ maxIndex = max (0 , calculateMaxIndex ()); // use zero when there are no children
10751107 }
1076- return inferredCount ;
1108+ return maxIndex ;
10771109 }
10781110
10791111 public int getCount () {
1080- return max (definedCount , getInferredCount ());
1112+ return max (definedCount , getMaxIndex ());
10811113 }
10821114
10831115 public void setCount (int count ) {
@@ -1179,7 +1211,7 @@ private PackedMap<Interval, MutableInt> getBackwardLinks() {
11791211 }
11801212
11811213 private void include (List <Arc > arcs , Interval key , MutableInt size ,
1182- boolean ignoreIfAlreadyPresent ) {
1214+ boolean ignoreIfAlreadyPresent ) {
11831215 /*
11841216 Remove self referential links.
11851217 These appear:
@@ -1341,19 +1373,18 @@ private boolean relax(int[] locations, Arc entry) {
13411373 }
13421374
13431375 private void init (int [] locations ) {
1344- Arrays .fill (locations , MIN_VALUE );
1345- locations [0 ] = 0 ;
1376+ Arrays .fill (locations , 0 );
13461377 }
13471378
13481379 private String arcsToString (List <Arc > arcs ) {
1349- String var = horizontal ? "c " : "r " ;
1380+ String var = horizontal ? "x " : "y " ;
13501381 StringBuilder result = new StringBuilder ();
1351- boolean first = false ;
1352- for (Arc arc : arcs ) {
1353- if (! first ) {
1354- first = true ;
1382+ boolean first = true ;
1383+ for (Arc arc : arcs ) {
1384+ if (first ) {
1385+ first = false ;
13551386 } else {
1356- result =result .append (", " );
1387+ result = result .append (", " );
13571388 }
13581389 int src = arc .span .min ;
13591390 int dst = arc .span .max ;
@@ -1434,10 +1465,6 @@ private void solve(Arc[] arcs, int[] locations) {
14341465 if (originalCulprits != null ) {
14351466 logError (axisName , arcs , originalCulprits );
14361467 }
1437- if (DEBUG ) {
1438- Log .v (TAG , axisName + " iteration completed in " +
1439- (1 + i ) + " steps of " + N );
1440- }
14411468 return ;
14421469 }
14431470 }
@@ -1506,6 +1533,18 @@ public int[] getTrailingMargins() {
15061533
15071534 private void computeLocations (int [] a ) {
15081535 solve (getArcs (), a );
1536+ if (!orderPreserved ) {
1537+ // Solve returns the smallest solution to the constraint system for which all
1538+ // values are positive. One value is therefore zero - though if the row/col
1539+ // order is not preserved this may not be the first vertex. For consistency,
1540+ // translate all the values so that they measure the distance from a[0]; the
1541+ // leading edge of the parent. After this transformation some values may be
1542+ // negative.
1543+ int a0 = a [0 ];
1544+ for (int i = 0 , N = a .length ; i < N ; i ++) {
1545+ a [i ] = a [i ] - a0 ;
1546+ }
1547+ }
15091548 }
15101549
15111550 public int [] getLocations () {
@@ -1521,7 +1560,10 @@ public int[] getLocations() {
15211560 }
15221561
15231562 private int size (int [] locations ) {
1524- return max2 (locations , 0 ) - locations [0 ];
1563+ // The parental edges are attached to vertices 0 and N - even when order is not
1564+ // being preserved and other vertices fall outside this range. Measure the distance
1565+ // between vertices 0 and N, assuming that locations[0] = 0.
1566+ return locations [getCount ()];
15251567 }
15261568
15271569 private void setParentConstraints (int min , int max ) {
@@ -1561,7 +1603,7 @@ public void layout(int size) {
15611603 }
15621604
15631605 public void invalidateStructure () {
1564- inferredCount = UNDEFINED ;
1606+ maxIndex = UNDEFINED ;
15651607
15661608 groupBounds = null ;
15671609 forwardLinks = null ;
@@ -2139,8 +2181,8 @@ public String toString() {
21392181
21402182 /**
21412183 * A Spec defines the horizontal or vertical characteristics of a group of
2142- * cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and
2143- * <em>flexibility</em> along the appropriate axis.
2184+ * cells. Each spec. defines the <em>grid indices</em> and <em>alignment</em>
2185+ * along the appropriate axis.
21442186 * <p>
21452187 * The <em>grid indices</em> are the leading and trailing edges of this cell group.
21462188 * See {@link GridLayout} for a description of the conventions used by GridLayout
@@ -2149,6 +2191,15 @@ public String toString() {
21492191 * The <em>alignment</em> property specifies how cells should be aligned in this group.
21502192 * For row groups, this specifies the vertical alignment.
21512193 * For column groups, this specifies the horizontal alignment.
2194+ * <p>
2195+ * Use the following static methods to create specs:
2196+ * <ul>
2197+ * <li>{@link #spec(int)}</li>
2198+ * <li>{@link #spec(int, int)}</li>
2199+ * <li>{@link #spec(int, Alignment)}</li>
2200+ * <li>{@link #spec(int, int, Alignment)}</li>
2201+ * </ul>
2202+ *
21522203 */
21532204 public static class Spec {
21542205 static final Spec UNDEFINED = spec (GridLayout .UNDEFINED );
0 commit comments