Add a new attribute to LinearLayout: useLargestChild.
Bug #2379138

This new attribute is to be used when the LinearLayout is wrap_content but you want
all the children inside to have the same dimension. Set useLargestChild to true and
give all the children a width/height of 0 and a weight of 1.0.
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 0ce70fa..5c78af5 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -94,6 +94,9 @@
     @ViewDebug.ExportedProperty
     private float mWeightSum;
 
+    @ViewDebug.ExportedProperty
+    private boolean mUseLargestChild;
+
     private int[] mMaxAscent;
     private int[] mMaxDescent;
 
@@ -102,7 +105,7 @@
     private static final int INDEX_CENTER_VERTICAL = 0;
     private static final int INDEX_TOP = 1;
     private static final int INDEX_BOTTOM = 2;
-    private static final int INDEX_FILL = 3;    
+    private static final int INDEX_FILL = 3;
 
     public LinearLayout(Context context) {
         super(context);
@@ -134,6 +137,9 @@
         mBaselineAlignedChildIndex =
                 a.getInt(com.android.internal.R.styleable.LinearLayout_baselineAlignedChildIndex, -1);
 
+        // TODO: Better name, add Java APIs, make it public
+        mUseLargestChild = a.getBoolean(R.styleable.LinearLayout_useLargestChild, false);
+
         a.recycle();
     }
 
@@ -328,6 +334,9 @@
         boolean matchWidth = false;
 
         final int baselineChildIndex = mBaselineAlignedChildIndex;        
+        final boolean useLargestChild = mUseLargestChild;
+
+        int largestChildHeight = Integer.MIN_VALUE;
 
         // See how tall everyone is. Also remember max width.
         for (int i = 0; i < count; ++i) {
@@ -353,30 +362,35 @@
                 // there is any leftover space.
                 mTotalLength += lp.topMargin + lp.bottomMargin;
             } else {
-               int oldHeight = Integer.MIN_VALUE;
+                int oldHeight = Integer.MIN_VALUE;
 
-               if (lp.height == 0 && lp.weight > 0) {
+                if (lp.height == 0 && lp.weight > 0) {
                    // heightMode is either UNSPECIFIED OR AT_MOST, and this child
                    // wanted to stretch to fill available space. Translate that to
                    // WRAP_CONTENT so that it does not end up with a height of 0
                    oldHeight = 0;
                    lp.height = LayoutParams.WRAP_CONTENT;
-               }
+                }
 
-               // Determine how big this child would like to.  If this or
-               // previous children have given a weight, then we allow it to
-               // use all available space (and we will shrink things later
-               // if needed).
-               measureChildBeforeLayout(
+                // Determine how big this child would like to.  If this or
+                // previous children have given a weight, then we allow it to
+                // use all available space (and we will shrink things later
+                // if needed).
+                measureChildBeforeLayout(
                        child, i, widthMeasureSpec, 0, heightMeasureSpec,
                        totalWeight == 0 ? mTotalLength : 0);
 
-               if (oldHeight != Integer.MIN_VALUE) {
+                if (oldHeight != Integer.MIN_VALUE) {
                    lp.height = oldHeight;
-               }
+                }
 
-               mTotalLength += child.getMeasuredHeight() + lp.topMargin +
+                final int childHeight = child.getMeasuredHeight();
+                mTotalLength += childHeight + lp.topMargin +
                        lp.bottomMargin + getNextLocationOffset(child);
+
+                if (useLargestChild) {
+                    largestChildHeight = Math.max(childHeight, largestChildHeight);
+                }
             }
 
             /**
@@ -426,7 +440,30 @@
 
             i += getChildrenSkipCount(child, i);
         }
-        
+
+        if (useLargestChild) {
+            mTotalLength = 0;
+
+            for (int i = 0; i < count; ++i) {
+                final View child = getVirtualChildAt(i);
+
+                if (child == null) {
+                    mTotalLength += measureNullChild(i);
+                    continue;
+                }
+
+                if (child.getVisibility() == GONE) {
+                    i += getChildrenSkipCount(child, i);
+                    continue;
+                }
+
+                final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+                        child.getLayoutParams();
+                mTotalLength += largestChildHeight + lp.topMargin+ lp.bottomMargin +
+                        getNextLocationOffset(child);
+            }
+        }
+
         // Add in our padding
         mTotalLength += mPaddingTop + mPaddingBottom;
 
@@ -587,6 +624,9 @@
         maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
 
         final boolean baselineAligned = mBaselineAligned;
+        final boolean useLargestChild = mUseLargestChild;
+
+        int largestChildWidth = Integer.MIN_VALUE;
 
         // See how wide everyone is. Also remember max height.
         for (int i = 0; i < count; ++i) {
@@ -602,7 +642,8 @@
                 continue;
             }
 
-            final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
+            final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+                    child.getLayoutParams();
 
             totalWeight += lp.weight;
             
@@ -643,9 +684,14 @@
                 if (oldWidth != Integer.MIN_VALUE) {
                     lp.width = oldWidth;
                 }
-               
-                mTotalLength += child.getMeasuredWidth() + lp.leftMargin +
-                        lp.rightMargin + getNextLocationOffset(child);
+
+                final int childWidth = child.getMeasuredWidth();
+                mTotalLength += childWidth + lp.leftMargin + lp.rightMargin +
+                        getNextLocationOffset(child);
+
+                if (useLargestChild) {
+                    largestChildWidth = Math.max(childWidth, largestChildWidth);
+                }
             }
 
             boolean matchHeightLocally = false;
@@ -708,6 +754,29 @@
             maxHeight = Math.max(maxHeight, ascent + descent);
         }
 
+        if (useLargestChild) {
+            mTotalLength = 0;
+
+            for (int i = 0; i < count; ++i) {
+                final View child = getVirtualChildAt(i);
+
+                if (child == null) {
+                    mTotalLength += measureNullChild(i);
+                    continue;
+                }
+
+                if (child.getVisibility() == GONE) {
+                    i += getChildrenSkipCount(child, i);
+                    continue;
+                }
+
+                final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+                        child.getLayoutParams();
+                mTotalLength += largestChildWidth + lp.leftMargin + lp.rightMargin +
+                        getNextLocationOffset(child);
+            }
+        }
+
         // Add in our padding
         mTotalLength += mPaddingLeft + mPaddingRight;
         
@@ -953,7 +1022,7 @@
         final int paddingLeft = mPaddingLeft;
 
         int childTop = mPaddingTop;
-        int childLeft = paddingLeft;
+        int childLeft;
         
         // Where right end of child should go
         final int width = mRight - mLeft;
@@ -1038,7 +1107,7 @@
     void layoutHorizontal() {
         final int paddingTop = mPaddingTop;
 
-        int childTop = paddingTop;
+        int childTop;
         int childLeft = mPaddingLeft;
         
         // Where bottom of child should go
@@ -1103,7 +1172,7 @@
                         break;
 
                     case Gravity.CENTER_VERTICAL:
-                        // Removed support for baselign alignment when layout_gravity or
+                        // Removed support for baseline alignment when layout_gravity or
                         // gravity == center_vertical. See bug #1038483.
                         // Keep the code around if we need to re-enable this feature
                         // if (childBaseline != -1) {
diff --git a/core/res/res/layout/alert_dialog.xml b/core/res/res/layout/alert_dialog.xml
index 409dcd3..4a63c5b 100644
--- a/core/res/res/layout/alert_dialog.xml
+++ b/core/res/res/layout/alert_dialog.xml
@@ -109,7 +109,8 @@
             android:orientation="horizontal"
             android:paddingTop="4dip"
             android:paddingLeft="2dip"
-            android:paddingRight="2dip" >
+            android:paddingRight="2dip"
+            android:useLargestChild="true">
             <LinearLayout android:id="@+id/leftSpacer"
                 android:layout_weight="0.25"
                 android:layout_width="0dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8dadd88..140ab09 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1700,6 +1700,10 @@
              space by giving it a layout_weight of 0.5 and setting the weightSum
              to 1.0. -->
         <attr name="weightSum" format="float" />
+        <!-- When set to true, all children with a weight will be considered having
+             the minimum size of the largest child. If false, all children are
+             measured normally. -->
+        <attr name="useLargestChild" format="boolean" />
     </declare-styleable>
     <declare-styleable name="ListView">
         <!-- Reference to an array resource that will populate the ListView.  For static content,