Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.widget;
     18 
     19 import com.android.internal.R;
     20 
     21 import android.content.Context;
     22 import android.content.res.TypedArray;
     23 import android.graphics.Canvas;
     24 import android.graphics.drawable.Drawable;
     25 import android.util.AttributeSet;
     26 import android.view.Gravity;
     27 import android.view.View;
     28 import android.view.ViewDebug;
     29 import android.view.ViewGroup;
     30 import android.widget.RemoteViews.RemoteView;
     31 
     32 
     33 /**
     34  * A Layout that arranges its children in a single column or a single row. The direction of
     35  * the row can be set by calling {@link #setOrientation(int) setOrientation()}.
     36  * You can also specify gravity, which specifies the alignment of all the child elements by
     37  * calling {@link #setGravity(int) setGravity()} or specify that specific children
     38  * grow to fill up any remaining space in the layout by setting the <em>weight</em> member of
     39  * {@link android.widget.LinearLayout.LayoutParams LinearLayout.LayoutParams}.
     40  * The default orientation is horizontal.
     41  *
     42  * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-linearlayout.html">Linear Layout
     43  * tutorial</a>.</p>
     44  *
     45  * <p>
     46  * Also see {@link LinearLayout.LayoutParams android.widget.LinearLayout.LayoutParams}
     47  * for layout attributes </p>
     48  *
     49  * @attr ref android.R.styleable#LinearLayout_baselineAligned
     50  * @attr ref android.R.styleable#LinearLayout_baselineAlignedChildIndex
     51  * @attr ref android.R.styleable#LinearLayout_gravity
     52  * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild
     53  * @attr ref android.R.styleable#LinearLayout_orientation
     54  * @attr ref android.R.styleable#LinearLayout_weightSum
     55  */
     56 @RemoteView
     57 public class LinearLayout extends ViewGroup {
     58     public static final int HORIZONTAL = 0;
     59     public static final int VERTICAL = 1;
     60 
     61     /**
     62      * Don't show any dividers.
     63      */
     64     public static final int SHOW_DIVIDER_NONE = 0;
     65     /**
     66      * Show a divider at the beginning of the group.
     67      */
     68     public static final int SHOW_DIVIDER_BEGINNING = 1;
     69     /**
     70      * Show dividers between each item in the group.
     71      */
     72     public static final int SHOW_DIVIDER_MIDDLE = 2;
     73     /**
     74      * Show a divider at the end of the group.
     75      */
     76     public static final int SHOW_DIVIDER_END = 4;
     77 
     78     /**
     79      * Whether the children of this layout are baseline aligned.  Only applicable
     80      * if {@link #mOrientation} is horizontal.
     81      */
     82     @ViewDebug.ExportedProperty(category = "layout")
     83     private boolean mBaselineAligned = true;
     84 
     85     /**
     86      * If this layout is part of another layout that is baseline aligned,
     87      * use the child at this index as the baseline.
     88      *
     89      * Note: this is orthogonal to {@link #mBaselineAligned}, which is concerned
     90      * with whether the children of this layout are baseline aligned.
     91      */
     92     @ViewDebug.ExportedProperty(category = "layout")
     93     private int mBaselineAlignedChildIndex = -1;
     94 
     95     /**
     96      * The additional offset to the child's baseline.
     97      * We'll calculate the baseline of this layout as we measure vertically; for
     98      * horizontal linear layouts, the offset of 0 is appropriate.
     99      */
    100     @ViewDebug.ExportedProperty(category = "measurement")
    101     private int mBaselineChildTop = 0;
    102 
    103     @ViewDebug.ExportedProperty(category = "measurement")
    104     private int mOrientation;
    105 
    106     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
    107             @ViewDebug.FlagToString(mask = -1,
    108                 equals = -1, name = "NONE"),
    109             @ViewDebug.FlagToString(mask = Gravity.NO_GRAVITY,
    110                 equals = Gravity.NO_GRAVITY,name = "NONE"),
    111             @ViewDebug.FlagToString(mask = Gravity.TOP,
    112                 equals = Gravity.TOP, name = "TOP"),
    113             @ViewDebug.FlagToString(mask = Gravity.BOTTOM,
    114                 equals = Gravity.BOTTOM, name = "BOTTOM"),
    115             @ViewDebug.FlagToString(mask = Gravity.LEFT,
    116                 equals = Gravity.LEFT, name = "LEFT"),
    117             @ViewDebug.FlagToString(mask = Gravity.RIGHT,
    118                 equals = Gravity.RIGHT, name = "RIGHT"),
    119             @ViewDebug.FlagToString(mask = Gravity.START,
    120                 equals = Gravity.START, name = "START"),
    121             @ViewDebug.FlagToString(mask = Gravity.END,
    122                 equals = Gravity.END, name = "END"),
    123             @ViewDebug.FlagToString(mask = Gravity.CENTER_VERTICAL,
    124                 equals = Gravity.CENTER_VERTICAL, name = "CENTER_VERTICAL"),
    125             @ViewDebug.FlagToString(mask = Gravity.FILL_VERTICAL,
    126                 equals = Gravity.FILL_VERTICAL, name = "FILL_VERTICAL"),
    127             @ViewDebug.FlagToString(mask = Gravity.CENTER_HORIZONTAL,
    128                 equals = Gravity.CENTER_HORIZONTAL, name = "CENTER_HORIZONTAL"),
    129             @ViewDebug.FlagToString(mask = Gravity.FILL_HORIZONTAL,
    130                 equals = Gravity.FILL_HORIZONTAL, name = "FILL_HORIZONTAL"),
    131             @ViewDebug.FlagToString(mask = Gravity.CENTER,
    132                 equals = Gravity.CENTER, name = "CENTER"),
    133             @ViewDebug.FlagToString(mask = Gravity.FILL,
    134                 equals = Gravity.FILL, name = "FILL"),
    135             @ViewDebug.FlagToString(mask = Gravity.RELATIVE_LAYOUT_DIRECTION,
    136                 equals = Gravity.RELATIVE_LAYOUT_DIRECTION, name = "RELATIVE")
    137         })
    138     private int mGravity = Gravity.START | Gravity.TOP;
    139 
    140     @ViewDebug.ExportedProperty(category = "measurement")
    141     private int mTotalLength;
    142 
    143     @ViewDebug.ExportedProperty(category = "layout")
    144     private float mWeightSum;
    145 
    146     @ViewDebug.ExportedProperty(category = "layout")
    147     private boolean mUseLargestChild;
    148 
    149     private int[] mMaxAscent;
    150     private int[] mMaxDescent;
    151 
    152     private static final int VERTICAL_GRAVITY_COUNT = 4;
    153 
    154     private static final int INDEX_CENTER_VERTICAL = 0;
    155     private static final int INDEX_TOP = 1;
    156     private static final int INDEX_BOTTOM = 2;
    157     private static final int INDEX_FILL = 3;
    158 
    159     private Drawable mDivider;
    160     private int mDividerWidth;
    161     private int mDividerHeight;
    162     private int mShowDividers;
    163     private int mDividerPadding;
    164 
    165     public LinearLayout(Context context) {
    166         super(context);
    167     }
    168 
    169     public LinearLayout(Context context, AttributeSet attrs) {
    170         this(context, attrs, 0);
    171     }
    172 
    173     public LinearLayout(Context context, AttributeSet attrs, int defStyle) {
    174         super(context, attrs, defStyle);
    175 
    176         TypedArray a = context.obtainStyledAttributes(attrs,
    177                 com.android.internal.R.styleable.LinearLayout, defStyle, 0);
    178 
    179         int index = a.getInt(com.android.internal.R.styleable.LinearLayout_orientation, -1);
    180         if (index >= 0) {
    181             setOrientation(index);
    182         }
    183 
    184         index = a.getInt(com.android.internal.R.styleable.LinearLayout_gravity, -1);
    185         if (index >= 0) {
    186             setGravity(index);
    187         }
    188 
    189         boolean baselineAligned = a.getBoolean(R.styleable.LinearLayout_baselineAligned, true);
    190         if (!baselineAligned) {
    191             setBaselineAligned(baselineAligned);
    192         }
    193 
    194         mWeightSum = a.getFloat(R.styleable.LinearLayout_weightSum, -1.0f);
    195 
    196         mBaselineAlignedChildIndex =
    197                 a.getInt(com.android.internal.R.styleable.LinearLayout_baselineAlignedChildIndex, -1);
    198 
    199         mUseLargestChild = a.getBoolean(R.styleable.LinearLayout_measureWithLargestChild, false);
    200 
    201         setDividerDrawable(a.getDrawable(R.styleable.LinearLayout_divider));
    202         mShowDividers = a.getInt(R.styleable.LinearLayout_showDividers, SHOW_DIVIDER_NONE);
    203         mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayout_dividerPadding, 0);
    204 
    205         a.recycle();
    206     }
    207 
    208     /**
    209      * Set how dividers should be shown between items in this layout
    210      *
    211      * @param showDividers One or more of {@link #SHOW_DIVIDER_BEGINNING},
    212      *                     {@link #SHOW_DIVIDER_MIDDLE}, or {@link #SHOW_DIVIDER_END},
    213      *                     or {@link #SHOW_DIVIDER_NONE} to show no dividers.
    214      */
    215     public void setShowDividers(int showDividers) {
    216         if (showDividers != mShowDividers) {
    217             requestLayout();
    218         }
    219         mShowDividers = showDividers;
    220     }
    221 
    222     @Override
    223     public boolean shouldDelayChildPressedState() {
    224         return false;
    225     }
    226 
    227     /**
    228      * @return A flag set indicating how dividers should be shown around items.
    229      * @see #setShowDividers(int)
    230      */
    231     public int getShowDividers() {
    232         return mShowDividers;
    233     }
    234 
    235     /**
    236      * Set a drawable to be used as a divider between items.
    237      * @param divider Drawable that will divide each item.
    238      * @see #setShowDividers(int)
    239      */
    240     public void setDividerDrawable(Drawable divider) {
    241         if (divider == mDivider) {
    242             return;
    243         }
    244         mDivider = divider;
    245         if (divider != null) {
    246             mDividerWidth = divider.getIntrinsicWidth();
    247             mDividerHeight = divider.getIntrinsicHeight();
    248         } else {
    249             mDividerWidth = 0;
    250             mDividerHeight = 0;
    251         }
    252         setWillNotDraw(divider == null);
    253         requestLayout();
    254     }
    255 
    256     /**
    257      * Set padding displayed on both ends of dividers.
    258      *
    259      * @param padding Padding value in pixels that will be applied to each end
    260      *
    261      * @see #setShowDividers(int)
    262      * @see #setDividerDrawable(Drawable)
    263      * @see #getDividerPadding()
    264      */
    265     public void setDividerPadding(int padding) {
    266         mDividerPadding = padding;
    267     }
    268 
    269     /**
    270      * Get the padding size used to inset dividers in pixels
    271      *
    272      * @see #setShowDividers(int)
    273      * @see #setDividerDrawable(Drawable)
    274      * @see #setDividerPadding(int)
    275      */
    276     public int getDividerPadding() {
    277         return mDividerPadding;
    278     }
    279 
    280     /**
    281      * Get the width of the current divider drawable.
    282      *
    283      * @hide Used internally by framework.
    284      */
    285     public int getDividerWidth() {
    286         return mDividerWidth;
    287     }
    288 
    289     @Override
    290     protected void onDraw(Canvas canvas) {
    291         if (mDivider == null) {
    292             return;
    293         }
    294 
    295         if (mOrientation == VERTICAL) {
    296             drawDividersVertical(canvas);
    297         } else {
    298             drawDividersHorizontal(canvas);
    299         }
    300     }
    301 
    302     void drawDividersVertical(Canvas canvas) {
    303         final int count = getVirtualChildCount();
    304         for (int i = 0; i < count; i++) {
    305             final View child = getVirtualChildAt(i);
    306 
    307             if (child != null && child.getVisibility() != GONE) {
    308                 if (hasDividerBeforeChildAt(i)) {
    309                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    310                     final int top = child.getTop() - lp.topMargin;
    311                     drawHorizontalDivider(canvas, top);
    312                 }
    313             }
    314         }
    315 
    316         if (hasDividerBeforeChildAt(count)) {
    317             final View child = getVirtualChildAt(count - 1);
    318             int bottom = 0;
    319             if (child == null) {
    320                 bottom = getHeight() - getPaddingBottom() - mDividerHeight;
    321             } else {
    322                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    323                 bottom = child.getBottom() + lp.bottomMargin;
    324             }
    325             drawHorizontalDivider(canvas, bottom);
    326         }
    327     }
    328 
    329     void drawDividersHorizontal(Canvas canvas) {
    330         final int count = getVirtualChildCount();
    331         for (int i = 0; i < count; i++) {
    332             final View child = getVirtualChildAt(i);
    333 
    334             if (child != null && child.getVisibility() != GONE) {
    335                 if (hasDividerBeforeChildAt(i)) {
    336                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    337                     final int left = child.getLeft() - lp.leftMargin;
    338                     drawVerticalDivider(canvas, left);
    339                 }
    340             }
    341         }
    342 
    343         if (hasDividerBeforeChildAt(count)) {
    344             final View child = getVirtualChildAt(count - 1);
    345             int right = 0;
    346             if (child == null) {
    347                 right = getWidth() - getPaddingRight() - mDividerWidth;
    348             } else {
    349                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    350                 right = child.getRight() + lp.rightMargin;
    351             }
    352             drawVerticalDivider(canvas, right);
    353         }
    354     }
    355 
    356     void drawHorizontalDivider(Canvas canvas, int top) {
    357         mDivider.setBounds(getPaddingLeft() + mDividerPadding, top,
    358                 getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight);
    359         mDivider.draw(canvas);
    360     }
    361 
    362     void drawVerticalDivider(Canvas canvas, int left) {
    363         mDivider.setBounds(left, getPaddingTop() + mDividerPadding,
    364                 left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding);
    365         mDivider.draw(canvas);
    366     }
    367 
    368     /**
    369      * <p>Indicates whether widgets contained within this layout are aligned
    370      * on their baseline or not.</p>
    371      *
    372      * @return true when widgets are baseline-aligned, false otherwise
    373      */
    374     public boolean isBaselineAligned() {
    375         return mBaselineAligned;
    376     }
    377 
    378     /**
    379      * <p>Defines whether widgets contained in this layout are
    380      * baseline-aligned or not.</p>
    381      *
    382      * @param baselineAligned true to align widgets on their baseline,
    383      *         false otherwise
    384      *
    385      * @attr ref android.R.styleable#LinearLayout_baselineAligned
    386      */
    387     @android.view.RemotableViewMethod
    388     public void setBaselineAligned(boolean baselineAligned) {
    389         mBaselineAligned = baselineAligned;
    390     }
    391 
    392     /**
    393      * When true, all children with a weight will be considered having
    394      * the minimum size of the largest child. If false, all children are
    395      * measured normally.
    396      *
    397      * @return True to measure children with a weight using the minimum
    398      *         size of the largest child, false otherwise.
    399      */
    400     public boolean isMeasureWithLargestChildEnabled() {
    401         return mUseLargestChild;
    402     }
    403 
    404     /**
    405      * When set to true, all children with a weight will be considered having
    406      * the minimum size of the largest child. If false, all children are
    407      * measured normally.
    408      *
    409      * Disabled by default.
    410      *
    411      * @param enabled True to measure children with a weight using the
    412      *        minimum size of the largest child, false otherwise.
    413      */
    414     @android.view.RemotableViewMethod
    415     public void setMeasureWithLargestChildEnabled(boolean enabled) {
    416         mUseLargestChild = enabled;
    417     }
    418 
    419     @Override
    420     public int getBaseline() {
    421         if (mBaselineAlignedChildIndex < 0) {
    422             return super.getBaseline();
    423         }
    424 
    425         if (getChildCount() <= mBaselineAlignedChildIndex) {
    426             throw new RuntimeException("mBaselineAlignedChildIndex of LinearLayout "
    427                     + "set to an index that is out of bounds.");
    428         }
    429 
    430         final View child = getChildAt(mBaselineAlignedChildIndex);
    431         final int childBaseline = child.getBaseline();
    432 
    433         if (childBaseline == -1) {
    434             if (mBaselineAlignedChildIndex == 0) {
    435                 // this is just the default case, safe to return -1
    436                 return -1;
    437             }
    438             // the user picked an index that points to something that doesn't
    439             // know how to calculate its baseline.
    440             throw new RuntimeException("mBaselineAlignedChildIndex of LinearLayout "
    441                     + "points to a View that doesn't know how to get its baseline.");
    442         }
    443 
    444         // TODO: This should try to take into account the virtual offsets
    445         // (See getNextLocationOffset and getLocationOffset)
    446         // We should add to childTop:
    447         // sum([getNextLocationOffset(getChildAt(i)) / i < mBaselineAlignedChildIndex])
    448         // and also add:
    449         // getLocationOffset(child)
    450         int childTop = mBaselineChildTop;
    451 
    452         if (mOrientation == VERTICAL) {
    453             final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
    454             if (majorGravity != Gravity.TOP) {
    455                switch (majorGravity) {
    456                    case Gravity.BOTTOM:
    457                        childTop = mBottom - mTop - mPaddingBottom - mTotalLength;
    458                        break;
    459 
    460                    case Gravity.CENTER_VERTICAL:
    461                        childTop += ((mBottom - mTop - mPaddingTop - mPaddingBottom) -
    462                                mTotalLength) / 2;
    463                        break;
    464                }
    465             }
    466         }
    467 
    468         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
    469         return childTop + lp.topMargin + childBaseline;
    470     }
    471 
    472     /**
    473      * @return The index of the child that will be used if this layout is
    474      *   part of a larger layout that is baseline aligned, or -1 if none has
    475      *   been set.
    476      */
    477     public int getBaselineAlignedChildIndex() {
    478         return mBaselineAlignedChildIndex;
    479     }
    480 
    481     /**
    482      * @param i The index of the child that will be used if this layout is
    483      *          part of a larger layout that is baseline aligned.
    484      *
    485      * @attr ref android.R.styleable#LinearLayout_baselineAlignedChildIndex
    486      */
    487     @android.view.RemotableViewMethod
    488     public void setBaselineAlignedChildIndex(int i) {
    489         if ((i < 0) || (i >= getChildCount())) {
    490             throw new IllegalArgumentException("base aligned child index out "
    491                     + "of range (0, " + getChildCount() + ")");
    492         }
    493         mBaselineAlignedChildIndex = i;
    494     }
    495 
    496     /**
    497      * <p>Returns the view at the specified index. This method can be overriden
    498      * to take into account virtual children. Refer to
    499      * {@link android.widget.TableLayout} and {@link android.widget.TableRow}
    500      * for an example.</p>
    501      *
    502      * @param index the child's index
    503      * @return the child at the specified index
    504      */
    505     View getVirtualChildAt(int index) {
    506         return getChildAt(index);
    507     }
    508 
    509     /**
    510      * <p>Returns the virtual number of children. This number might be different
    511      * than the actual number of children if the layout can hold virtual
    512      * children. Refer to
    513      * {@link android.widget.TableLayout} and {@link android.widget.TableRow}
    514      * for an example.</p>
    515      *
    516      * @return the virtual number of children
    517      */
    518     int getVirtualChildCount() {
    519         return getChildCount();
    520     }
    521 
    522     /**
    523      * Returns the desired weights sum.
    524      *
    525      * @return A number greater than 0.0f if the weight sum is defined, or
    526      *         a number lower than or equals to 0.0f if not weight sum is
    527      *         to be used.
    528      */
    529     public float getWeightSum() {
    530         return mWeightSum;
    531     }
    532 
    533     /**
    534      * Defines the desired weights sum. If unspecified the weights sum is computed
    535      * at layout time by adding the layout_weight of each child.
    536      *
    537      * This can be used for instance to give a single child 50% of the total
    538      * available space by giving it a layout_weight of 0.5 and setting the
    539      * weightSum to 1.0.
    540      *
    541      * @param weightSum a number greater than 0.0f, or a number lower than or equals
    542      *        to 0.0f if the weight sum should be computed from the children's
    543      *        layout_weight
    544      */
    545     @android.view.RemotableViewMethod
    546     public void setWeightSum(float weightSum) {
    547         mWeightSum = Math.max(0.0f, weightSum);
    548     }
    549 
    550     @Override
    551     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    552         if (mOrientation == VERTICAL) {
    553             measureVertical(widthMeasureSpec, heightMeasureSpec);
    554         } else {
    555             measureHorizontal(widthMeasureSpec, heightMeasureSpec);
    556         }
    557     }
    558 
    559     /**
    560      * Determines where to position dividers between children.
    561      *
    562      * @param childIndex Index of child to check for preceding divider
    563      * @return true if there should be a divider before the child at childIndex
    564      * @hide Pending API consideration. Currently only used internally by the system.
    565      */
    566     protected boolean hasDividerBeforeChildAt(int childIndex) {
    567         if (childIndex == 0) {
    568             return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0;
    569         } else if (childIndex == getChildCount()) {
    570             return (mShowDividers & SHOW_DIVIDER_END) != 0;
    571         } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) {
    572             boolean hasVisibleViewBefore = false;
    573             for (int i = childIndex - 1; i >= 0; i--) {
    574                 if (getChildAt(i).getVisibility() != GONE) {
    575                     hasVisibleViewBefore = true;
    576                     break;
    577                 }
    578             }
    579             return hasVisibleViewBefore;
    580         }
    581         return false;
    582     }
    583 
    584     /**
    585      * Measures the children when the orientation of this LinearLayout is set
    586      * to {@link #VERTICAL}.
    587      *
    588      * @param widthMeasureSpec Horizontal space requirements as imposed by the parent.
    589      * @param heightMeasureSpec Vertical space requirements as imposed by the parent.
    590      *
    591      * @see #getOrientation()
    592      * @see #setOrientation(int)
    593      * @see #onMeasure(int, int)
    594      */
    595     void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
    596         mTotalLength = 0;
    597         int maxWidth = 0;
    598         int childState = 0;
    599         int alternativeMaxWidth = 0;
    600         int weightedMaxWidth = 0;
    601         boolean allFillParent = true;
    602         float totalWeight = 0;
    603 
    604         final int count = getVirtualChildCount();
    605 
    606         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    607         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    608 
    609         boolean matchWidth = false;
    610 
    611         final int baselineChildIndex = mBaselineAlignedChildIndex;
    612         final boolean useLargestChild = mUseLargestChild;
    613 
    614         int largestChildHeight = Integer.MIN_VALUE;
    615 
    616         // See how tall everyone is. Also remember max width.
    617         for (int i = 0; i < count; ++i) {
    618             final View child = getVirtualChildAt(i);
    619 
    620             if (child == null) {
    621                 mTotalLength += measureNullChild(i);
    622                 continue;
    623             }
    624 
    625             if (child.getVisibility() == View.GONE) {
    626                i += getChildrenSkipCount(child, i);
    627                continue;
    628             }
    629 
    630             if (hasDividerBeforeChildAt(i)) {
    631                 mTotalLength += mDividerHeight;
    632             }
    633 
    634             LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
    635 
    636             totalWeight += lp.weight;
    637 
    638             if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) {
    639                 // Optimization: don't bother measuring children who are going to use
    640                 // leftover space. These views will get measured again down below if
    641                 // there is any leftover space.
    642                 final int totalLength = mTotalLength;
    643                 mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);
    644             } else {
    645                 int oldHeight = Integer.MIN_VALUE;
    646 
    647                 if (lp.height == 0 && lp.weight > 0) {
    648                     // heightMode is either UNSPECIFIED or AT_MOST, and this
    649                     // child wanted to stretch to fill available space.
    650                     // Translate that to WRAP_CONTENT so that it does not end up
    651                     // with a height of 0
    652                     oldHeight = 0;
    653                     lp.height = LayoutParams.WRAP_CONTENT;
    654                 }
    655 
    656                 // Determine how big this child would like to be. If this or
    657                 // previous children have given a weight, then we allow it to
    658                 // use all available space (and we will shrink things later
    659                 // if needed).
    660                 measureChildBeforeLayout(
    661                        child, i, widthMeasureSpec, 0, heightMeasureSpec,
    662                        totalWeight == 0 ? mTotalLength : 0);
    663 
    664                 if (oldHeight != Integer.MIN_VALUE) {
    665                    lp.height = oldHeight;
    666                 }
    667 
    668                 final int childHeight = child.getMeasuredHeight();
    669                 final int totalLength = mTotalLength;
    670                 mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +
    671                        lp.bottomMargin + getNextLocationOffset(child));
    672 
    673                 if (useLargestChild) {
    674                     largestChildHeight = Math.max(childHeight, largestChildHeight);
    675                 }
    676             }
    677 
    678             /**
    679              * If applicable, compute the additional offset to the child's baseline
    680              * we'll need later when asked {@link #getBaseline}.
    681              */
    682             if ((baselineChildIndex >= 0) && (baselineChildIndex == i + 1)) {
    683                mBaselineChildTop = mTotalLength;
    684             }
    685 
    686             // if we are trying to use a child index for our baseline, the above
    687             // book keeping only works if there are no children above it with
    688             // weight.  fail fast to aid the developer.
    689             if (i < baselineChildIndex && lp.weight > 0) {
    690                 throw new RuntimeException("A child of LinearLayout with index "
    691                         + "less than mBaselineAlignedChildIndex has weight > 0, which "
    692                         + "won't work.  Either remove the weight, or don't set "
    693                         + "mBaselineAlignedChildIndex.");
    694             }
    695 
    696             boolean matchWidthLocally = false;
    697             if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.MATCH_PARENT) {
    698                 // The width of the linear layout will scale, and at least one
    699                 // child said it wanted to match our width. Set a flag
    700                 // indicating that we need to remeasure at least that view when
    701                 // we know our width.
    702                 matchWidth = true;
    703                 matchWidthLocally = true;
    704             }
    705 
    706             final int margin = lp.leftMargin + lp.rightMargin;
    707             final int measuredWidth = child.getMeasuredWidth() + margin;
    708             maxWidth = Math.max(maxWidth, measuredWidth);
    709             childState = combineMeasuredStates(childState, child.getMeasuredState());
    710 
    711             allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;
    712             if (lp.weight > 0) {
    713                 /*
    714                  * Widths of weighted Views are bogus if we end up
    715                  * remeasuring, so keep them separate.
    716                  */
    717                 weightedMaxWidth = Math.max(weightedMaxWidth,
    718                         matchWidthLocally ? margin : measuredWidth);
    719             } else {
    720                 alternativeMaxWidth = Math.max(alternativeMaxWidth,
    721                         matchWidthLocally ? margin : measuredWidth);
    722             }
    723 
    724             i += getChildrenSkipCount(child, i);
    725         }
    726 
    727         if (mTotalLength > 0 && hasDividerBeforeChildAt(count)) {
    728             mTotalLength += mDividerHeight;
    729         }
    730 
    731         if (useLargestChild &&
    732                 (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) {
    733             mTotalLength = 0;
    734 
    735             for (int i = 0; i < count; ++i) {
    736                 final View child = getVirtualChildAt(i);
    737 
    738                 if (child == null) {
    739                     mTotalLength += measureNullChild(i);
    740                     continue;
    741                 }
    742 
    743                 if (child.getVisibility() == GONE) {
    744                     i += getChildrenSkipCount(child, i);
    745                     continue;
    746                 }
    747 
    748                 final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
    749                         child.getLayoutParams();
    750                 // Account for negative margins
    751                 final int totalLength = mTotalLength;
    752                 mTotalLength = Math.max(totalLength, totalLength + largestChildHeight +
    753                         lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));
    754             }
    755         }
    756 
    757         // Add in our padding
    758         mTotalLength += mPaddingTop + mPaddingBottom;
    759 
    760         int heightSize = mTotalLength;
    761 
    762         // Check against our minimum height
    763         heightSize = Math.max(heightSize, getSuggestedMinimumHeight());
    764 
    765         // Reconcile our calculated size with the heightMeasureSpec
    766         int heightSizeAndState = resolveSizeAndState(heightSize, heightMeasureSpec, 0);
    767         heightSize = heightSizeAndState & MEASURED_SIZE_MASK;
    768 
    769         // Either expand children with weight to take up available space or
    770         // shrink them if they extend beyond our current bounds
    771         int delta = heightSize - mTotalLength;
    772         if (delta != 0 && totalWeight > 0.0f) {
    773             float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
    774 
    775             mTotalLength = 0;
    776 
    777             for (int i = 0; i < count; ++i) {
    778                 final View child = getVirtualChildAt(i);
    779 
    780                 if (child.getVisibility() == View.GONE) {
    781                     continue;
    782                 }
    783 
    784                 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
    785 
    786                 float childExtra = lp.weight;
    787                 if (childExtra > 0) {
    788                     // Child said it could absorb extra space -- give him his share
    789                     int share = (int) (childExtra * delta / weightSum);
    790                     weightSum -= childExtra;
    791                     delta -= share;
    792 
    793                     final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
    794                             mPaddingLeft + mPaddingRight +
    795                                     lp.leftMargin + lp.rightMargin, lp.width);
    796 
    797                     // TODO: Use a field like lp.isMeasured to figure out if this
    798                     // child has been previously measured
    799                     if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) {
    800                         // child was measured once already above...
    801                         // base new measurement on stored values
    802                         int childHeight = child.getMeasuredHeight() + share;
    803                         if (childHeight < 0) {
    804                             childHeight = 0;
    805                         }
    806 
    807                         child.measure(childWidthMeasureSpec,
    808                                 MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
    809                     } else {
    810                         // child was skipped in the loop above.
    811                         // Measure for this first time here
    812                         child.measure(childWidthMeasureSpec,
    813                                 MeasureSpec.makeMeasureSpec(share > 0 ? share : 0,
    814                                         MeasureSpec.EXACTLY));
    815                     }
    816 
    817                     // Child may now not fit in vertical dimension.
    818                     childState = combineMeasuredStates(childState, child.getMeasuredState()
    819                             & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
    820                 }
    821 
    822                 final int margin =  lp.leftMargin + lp.rightMargin;
    823                 final int measuredWidth = child.getMeasuredWidth() + margin;
    824                 maxWidth = Math.max(maxWidth, measuredWidth);
    825 
    826                 boolean matchWidthLocally = widthMode != MeasureSpec.EXACTLY &&
    827                         lp.width == LayoutParams.MATCH_PARENT;
    828 
    829                 alternativeMaxWidth = Math.max(alternativeMaxWidth,
    830                         matchWidthLocally ? margin : measuredWidth);
    831 
    832                 allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;
    833 
    834                 final int totalLength = mTotalLength;
    835                 mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredHeight() +
    836                         lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));
    837             }
    838 
    839             // Add in our padding
    840             mTotalLength += mPaddingTop + mPaddingBottom;
    841             // TODO: Should we recompute the heightSpec based on the new total length?
    842         } else {
    843             alternativeMaxWidth = Math.max(alternativeMaxWidth,
    844                                            weightedMaxWidth);
    845 
    846 
    847             // We have no limit, so make all weighted views as tall as the largest child.
    848             // Children will have already been measured once.
    849             if (useLargestChild && widthMode == MeasureSpec.UNSPECIFIED) {
    850                 for (int i = 0; i < count; i++) {
    851                     final View child = getVirtualChildAt(i);
    852 
    853                     if (child == null || child.getVisibility() == View.GONE) {
    854                         continue;
    855                     }
    856 
    857                     final LinearLayout.LayoutParams lp =
    858                             (LinearLayout.LayoutParams) child.getLayoutParams();
    859 
    860                     float childExtra = lp.weight;
    861                     if (childExtra > 0) {
    862                         child.measure(
    863                                 MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(),
    864                                         MeasureSpec.EXACTLY),
    865                                 MeasureSpec.makeMeasureSpec(largestChildHeight,
    866                                         MeasureSpec.EXACTLY));
    867                     }
    868                 }
    869             }
    870         }
    871 
    872         if (!allFillParent && widthMode != MeasureSpec.EXACTLY) {
    873             maxWidth = alternativeMaxWidth;
    874         }
    875 
    876         maxWidth += mPaddingLeft + mPaddingRight;
    877 
    878         // Check against our minimum width
    879         maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
    880 
    881         setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
    882                 heightSizeAndState);
    883 
    884         if (matchWidth) {
    885             forceUniformWidth(count, heightMeasureSpec);
    886         }
    887     }
    888 
    889     private void forceUniformWidth(int count, int heightMeasureSpec) {
    890         // Pretend that the linear layout has an exact size.
    891         int uniformMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(),
    892                 MeasureSpec.EXACTLY);
    893         for (int i = 0; i< count; ++i) {
    894            final View child = getVirtualChildAt(i);
    895            if (child.getVisibility() != GONE) {
    896                LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams)child.getLayoutParams());
    897 
    898                if (lp.width == LayoutParams.MATCH_PARENT) {
    899                    // Temporarily force children to reuse their old measured height
    900                    // FIXME: this may not be right for something like wrapping text?
    901                    int oldHeight = lp.height;
    902                    lp.height = child.getMeasuredHeight();
    903 
    904                    // Remeasue with new dimensions
    905                    measureChildWithMargins(child, uniformMeasureSpec, 0, heightMeasureSpec, 0);
    906                    lp.height = oldHeight;
    907                }
    908            }
    909         }
    910     }
    911 
    912     /**
    913      * Measures the children when the orientation of this LinearLayout is set
    914      * to {@link #HORIZONTAL}.
    915      *
    916      * @param widthMeasureSpec Horizontal space requirements as imposed by the parent.
    917      * @param heightMeasureSpec Vertical space requirements as imposed by the parent.
    918      *
    919      * @see #getOrientation()
    920      * @see #setOrientation(int)
    921      * @see #onMeasure(int, int)
    922      */
    923     void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
    924         mTotalLength = 0;
    925         int maxHeight = 0;
    926         int childState = 0;
    927         int alternativeMaxHeight = 0;
    928         int weightedMaxHeight = 0;
    929         boolean allFillParent = true;
    930         float totalWeight = 0;
    931 
    932         final int count = getVirtualChildCount();
    933 
    934         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    935         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    936 
    937         boolean matchHeight = false;
    938 
    939         if (mMaxAscent == null || mMaxDescent == null) {
    940             mMaxAscent = new int[VERTICAL_GRAVITY_COUNT];
    941             mMaxDescent = new int[VERTICAL_GRAVITY_COUNT];
    942         }
    943 
    944         final int[] maxAscent = mMaxAscent;
    945         final int[] maxDescent = mMaxDescent;
    946 
    947         maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
    948         maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
    949 
    950         final boolean baselineAligned = mBaselineAligned;
    951         final boolean useLargestChild = mUseLargestChild;
    952 
    953         final boolean isExactly = widthMode == MeasureSpec.EXACTLY;
    954 
    955         int largestChildWidth = Integer.MIN_VALUE;
    956 
    957         // See how wide everyone is. Also remember max height.
    958         for (int i = 0; i < count; ++i) {
    959             final View child = getVirtualChildAt(i);
    960 
    961             if (child == null) {
    962                 mTotalLength += measureNullChild(i);
    963                 continue;
    964             }
    965 
    966             if (child.getVisibility() == GONE) {
    967                 i += getChildrenSkipCount(child, i);
    968                 continue;
    969             }
    970 
    971             if (hasDividerBeforeChildAt(i)) {
    972                 mTotalLength += mDividerWidth;
    973             }
    974 
    975             final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
    976                     child.getLayoutParams();
    977 
    978             totalWeight += lp.weight;
    979 
    980             if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) {
    981                 // Optimization: don't bother measuring children who are going to use
    982                 // leftover space. These views will get measured again down below if
    983                 // there is any leftover space.
    984                 if (isExactly) {
    985                     mTotalLength += lp.leftMargin + lp.rightMargin;
    986                 } else {
    987                     final int totalLength = mTotalLength;
    988                     mTotalLength = Math.max(totalLength, totalLength +
    989                             lp.leftMargin + lp.rightMargin);
    990                 }
    991 
    992                 // Baseline alignment requires to measure widgets to obtain the
    993                 // baseline offset (in particular for TextViews). The following
    994                 // defeats the optimization mentioned above. Allow the child to
    995                 // use as much space as it wants because we can shrink things
    996                 // later (and re-measure).
    997                 if (baselineAligned) {
    998                     final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    999                     child.measure(freeSpec, freeSpec);
   1000                 }
   1001             } else {
   1002                 int oldWidth = Integer.MIN_VALUE;
   1003 
   1004                 if (lp.width == 0 && lp.weight > 0) {
   1005                     // widthMode is either UNSPECIFIED or AT_MOST, and this
   1006                     // child
   1007                     // wanted to stretch to fill available space. Translate that to
   1008                     // WRAP_CONTENT so that it does not end up with a width of 0
   1009                     oldWidth = 0;
   1010                     lp.width = LayoutParams.WRAP_CONTENT;
   1011                 }
   1012 
   1013                 // Determine how big this child would like to be. If this or
   1014                 // previous children have given a weight, then we allow it to
   1015                 // use all available space (and we will shrink things later
   1016                 // if needed).
   1017                 measureChildBeforeLayout(child, i, widthMeasureSpec,
   1018                         totalWeight == 0 ? mTotalLength : 0,
   1019                         heightMeasureSpec, 0);
   1020 
   1021                 if (oldWidth != Integer.MIN_VALUE) {
   1022                     lp.width = oldWidth;
   1023                 }
   1024 
   1025                 final int childWidth = child.getMeasuredWidth();
   1026                 if (isExactly) {
   1027                     mTotalLength += childWidth + lp.leftMargin + lp.rightMargin +
   1028                             getNextLocationOffset(child);
   1029                 } else {
   1030                     final int totalLength = mTotalLength;
   1031                     mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin +
   1032                            lp.rightMargin + getNextLocationOffset(child));
   1033                 }
   1034 
   1035                 if (useLargestChild) {
   1036                     largestChildWidth = Math.max(childWidth, largestChildWidth);
   1037                 }
   1038             }
   1039 
   1040             boolean matchHeightLocally = false;
   1041             if (heightMode != MeasureSpec.EXACTLY && lp.height == LayoutParams.MATCH_PARENT) {
   1042                 // The height of the linear layout will scale, and at least one
   1043                 // child said it wanted to match our height. Set a flag indicating that
   1044                 // we need to remeasure at least that view when we know our height.
   1045                 matchHeight = true;
   1046                 matchHeightLocally = true;
   1047             }
   1048 
   1049             final int margin = lp.topMargin + lp.bottomMargin;
   1050             final int childHeight = child.getMeasuredHeight() + margin;
   1051             childState = combineMeasuredStates(childState, child.getMeasuredState());
   1052 
   1053             if (baselineAligned) {
   1054                 final int childBaseline = child.getBaseline();
   1055                 if (childBaseline != -1) {
   1056                     // Translates the child's vertical gravity into an index
   1057                     // in the range 0..VERTICAL_GRAVITY_COUNT
   1058                     final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity)
   1059                             & Gravity.VERTICAL_GRAVITY_MASK;
   1060                     final int index = ((gravity >> Gravity.AXIS_Y_SHIFT)
   1061                             & ~Gravity.AXIS_SPECIFIED) >> 1;
   1062 
   1063                     maxAscent[index] = Math.max(maxAscent[index], childBaseline);
   1064                     maxDescent[index] = Math.max(maxDescent[index], childHeight - childBaseline);
   1065                 }
   1066             }
   1067 
   1068             maxHeight = Math.max(maxHeight, childHeight);
   1069 
   1070             allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT;
   1071             if (lp.weight > 0) {
   1072                 /*
   1073                  * Heights of weighted Views are bogus if we end up
   1074                  * remeasuring, so keep them separate.
   1075                  */
   1076                 weightedMaxHeight = Math.max(weightedMaxHeight,
   1077                         matchHeightLocally ? margin : childHeight);
   1078             } else {
   1079                 alternativeMaxHeight = Math.max(alternativeMaxHeight,
   1080                         matchHeightLocally ? margin : childHeight);
   1081             }
   1082 
   1083             i += getChildrenSkipCount(child, i);
   1084         }
   1085 
   1086         if (mTotalLength > 0 && hasDividerBeforeChildAt(count)) {
   1087             mTotalLength += mDividerWidth;
   1088         }
   1089 
   1090         // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP,
   1091         // the most common case
   1092         if (maxAscent[INDEX_TOP] != -1 ||
   1093                 maxAscent[INDEX_CENTER_VERTICAL] != -1 ||
   1094                 maxAscent[INDEX_BOTTOM] != -1 ||
   1095                 maxAscent[INDEX_FILL] != -1) {
   1096             final int ascent = Math.max(maxAscent[INDEX_FILL],
   1097                     Math.max(maxAscent[INDEX_CENTER_VERTICAL],
   1098                     Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM])));
   1099             final int descent = Math.max(maxDescent[INDEX_FILL],
   1100                     Math.max(maxDescent[INDEX_CENTER_VERTICAL],
   1101                     Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM])));
   1102             maxHeight = Math.max(maxHeight, ascent + descent);
   1103         }
   1104 
   1105         if (useLargestChild &&
   1106                 (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED)) {
   1107             mTotalLength = 0;
   1108 
   1109             for (int i = 0; i < count; ++i) {
   1110                 final View child = getVirtualChildAt(i);
   1111 
   1112                 if (child == null) {
   1113                     mTotalLength += measureNullChild(i);
   1114                     continue;
   1115                 }
   1116 
   1117                 if (child.getVisibility() == GONE) {
   1118                     i += getChildrenSkipCount(child, i);
   1119                     continue;
   1120                 }
   1121 
   1122                 final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
   1123                         child.getLayoutParams();
   1124                 if (isExactly) {
   1125                     mTotalLength += largestChildWidth + lp.leftMargin + lp.rightMargin +
   1126                             getNextLocationOffset(child);
   1127                 } else {
   1128                     final int totalLength = mTotalLength;
   1129                     mTotalLength = Math.max(totalLength, totalLength + largestChildWidth +
   1130                             lp.leftMargin + lp.rightMargin + getNextLocationOffset(child));
   1131                 }
   1132             }
   1133         }
   1134 
   1135         // Add in our padding
   1136         mTotalLength += mPaddingLeft + mPaddingRight;
   1137 
   1138         int widthSize = mTotalLength;
   1139 
   1140         // Check against our minimum width
   1141         widthSize = Math.max(widthSize, getSuggestedMinimumWidth());
   1142 
   1143         // Reconcile our calculated size with the widthMeasureSpec
   1144         int widthSizeAndState = resolveSizeAndState(widthSize, widthMeasureSpec, 0);
   1145         widthSize = widthSizeAndState & MEASURED_SIZE_MASK;
   1146 
   1147         // Either expand children with weight to take up available space or
   1148         // shrink them if they extend beyond our current bounds
   1149         int delta = widthSize - mTotalLength;
   1150         if (delta != 0 && totalWeight > 0.0f) {
   1151             float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
   1152 
   1153             maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
   1154             maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
   1155             maxHeight = -1;
   1156 
   1157             mTotalLength = 0;
   1158 
   1159             for (int i = 0; i < count; ++i) {
   1160                 final View child = getVirtualChildAt(i);
   1161 
   1162                 if (child == null || child.getVisibility() == View.GONE) {
   1163                     continue;
   1164                 }
   1165 
   1166                 final LinearLayout.LayoutParams lp =
   1167                         (LinearLayout.LayoutParams) child.getLayoutParams();
   1168 
   1169                 float childExtra = lp.weight;
   1170                 if (childExtra > 0) {
   1171                     // Child said it could absorb extra space -- give him his share
   1172                     int share = (int) (childExtra * delta / weightSum);
   1173                     weightSum -= childExtra;
   1174                     delta -= share;
   1175 
   1176                     final int childHeightMeasureSpec = getChildMeasureSpec(
   1177                             heightMeasureSpec,
   1178                             mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin,
   1179                             lp.height);
   1180 
   1181                     // TODO: Use a field like lp.isMeasured to figure out if this
   1182                     // child has been previously measured
   1183                     if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) {
   1184                         // child was measured once already above ... base new measurement
   1185                         // on stored values
   1186                         int childWidth = child.getMeasuredWidth() + share;
   1187                         if (childWidth < 0) {
   1188                             childWidth = 0;
   1189                         }
   1190 
   1191                         child.measure(
   1192                             MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
   1193                             childHeightMeasureSpec);
   1194                     } else {
   1195                         // child was skipped in the loop above. Measure for this first time here
   1196                         child.measure(MeasureSpec.makeMeasureSpec(
   1197                                 share > 0 ? share : 0, MeasureSpec.EXACTLY),
   1198                                 childHeightMeasureSpec);
   1199                     }
   1200 
   1201                     // Child may now not fit in horizontal dimension.
   1202                     childState = combineMeasuredStates(childState,
   1203                             child.getMeasuredState() & MEASURED_STATE_MASK);
   1204                 }
   1205 
   1206                 if (isExactly) {
   1207                     mTotalLength += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin +
   1208                             getNextLocationOffset(child);
   1209                 } else {
   1210                     final int totalLength = mTotalLength;
   1211                     mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredWidth() +
   1212                             lp.leftMargin + lp.rightMargin + getNextLocationOffset(child));
   1213                 }
   1214 
   1215                 boolean matchHeightLocally = heightMode != MeasureSpec.EXACTLY &&
   1216                         lp.height == LayoutParams.MATCH_PARENT;
   1217 
   1218                 final int margin = lp.topMargin + lp .bottomMargin;
   1219                 int childHeight = child.getMeasuredHeight() + margin;
   1220                 maxHeight = Math.max(maxHeight, childHeight);
   1221                 alternativeMaxHeight = Math.max(alternativeMaxHeight,
   1222                         matchHeightLocally ? margin : childHeight);
   1223 
   1224                 allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT;
   1225 
   1226                 if (baselineAligned) {
   1227                     final int childBaseline = child.getBaseline();
   1228                     if (childBaseline != -1) {
   1229                         // Translates the child's vertical gravity into an index in the range 0..2
   1230                         final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity)
   1231                                 & Gravity.VERTICAL_GRAVITY_MASK;
   1232                         final int index = ((gravity >> Gravity.AXIS_Y_SHIFT)
   1233                                 & ~Gravity.AXIS_SPECIFIED) >> 1;
   1234 
   1235                         maxAscent[index] = Math.max(maxAscent[index], childBaseline);
   1236                         maxDescent[index] = Math.max(maxDescent[index],
   1237                                 childHeight - childBaseline);
   1238                     }
   1239                 }
   1240             }
   1241 
   1242             // Add in our padding
   1243             mTotalLength += mPaddingLeft + mPaddingRight;
   1244             // TODO: Should we update widthSize with the new total length?
   1245 
   1246             // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP,
   1247             // the most common case
   1248             if (maxAscent[INDEX_TOP] != -1 ||
   1249                     maxAscent[INDEX_CENTER_VERTICAL] != -1 ||
   1250                     maxAscent[INDEX_BOTTOM] != -1 ||
   1251                     maxAscent[INDEX_FILL] != -1) {
   1252                 final int ascent = Math.max(maxAscent[INDEX_FILL],
   1253                         Math.max(maxAscent[INDEX_CENTER_VERTICAL],
   1254                         Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM])));
   1255                 final int descent = Math.max(maxDescent[INDEX_FILL],
   1256                         Math.max(maxDescent[INDEX_CENTER_VERTICAL],
   1257                         Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM])));
   1258                 maxHeight = Math.max(maxHeight, ascent + descent);
   1259             }
   1260         } else {
   1261             alternativeMaxHeight = Math.max(alternativeMaxHeight, weightedMaxHeight);
   1262 
   1263             // We have no limit, so make all weighted views as wide as the largest child.
   1264             // Children will have already been measured once.
   1265             if (useLargestChild && widthMode == MeasureSpec.UNSPECIFIED) {
   1266                 for (int i = 0; i < count; i++) {
   1267                     final View child = getVirtualChildAt(i);
   1268 
   1269                     if (child == null || child.getVisibility() == View.GONE) {
   1270                         continue;
   1271                     }
   1272 
   1273                     final LinearLayout.LayoutParams lp =
   1274                             (LinearLayout.LayoutParams) child.getLayoutParams();
   1275 
   1276                     float childExtra = lp.weight;
   1277                     if (childExtra > 0) {
   1278                         child.measure(
   1279                                 MeasureSpec.makeMeasureSpec(largestChildWidth, MeasureSpec.EXACTLY),
   1280                                 MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(),
   1281                                         MeasureSpec.EXACTLY));
   1282                     }
   1283                 }
   1284             }
   1285         }
   1286 
   1287         if (!allFillParent && heightMode != MeasureSpec.EXACTLY) {
   1288             maxHeight = alternativeMaxHeight;
   1289         }
   1290 
   1291         maxHeight += mPaddingTop + mPaddingBottom;
   1292 
   1293         // Check against our minimum height
   1294         maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
   1295 
   1296         setMeasuredDimension(widthSizeAndState | (childState&MEASURED_STATE_MASK),
   1297                 resolveSizeAndState(maxHeight, heightMeasureSpec,
   1298                         (childState<<MEASURED_HEIGHT_STATE_SHIFT)));
   1299 
   1300         if (matchHeight) {
   1301             forceUniformHeight(count, widthMeasureSpec);
   1302         }
   1303     }
   1304 
   1305     private void forceUniformHeight(int count, int widthMeasureSpec) {
   1306         // Pretend that the linear layout has an exact size. This is the measured height of
   1307         // ourselves. The measured height should be the max height of the children, changed
   1308         // to accomodate the heightMesureSpec from the parent
   1309         int uniformMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
   1310                 MeasureSpec.EXACTLY);
   1311         for (int i = 0; i < count; ++i) {
   1312            final View child = getVirtualChildAt(i);
   1313            if (child.getVisibility() != GONE) {
   1314                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
   1315 
   1316                if (lp.height == LayoutParams.MATCH_PARENT) {
   1317                    // Temporarily force children to reuse their old measured width
   1318                    // FIXME: this may not be right for something like wrapping text?
   1319                    int oldWidth = lp.width;
   1320                    lp.width = child.getMeasuredWidth();
   1321 
   1322                    // Remeasure with new dimensions
   1323                    measureChildWithMargins(child, widthMeasureSpec, 0, uniformMeasureSpec, 0);
   1324                    lp.width = oldWidth;
   1325                }
   1326            }
   1327         }
   1328     }
   1329 
   1330     /**
   1331      * <p>Returns the number of children to skip after measuring/laying out
   1332      * the specified child.</p>
   1333      *
   1334      * @param child the child after which we want to skip children
   1335      * @param index the index of the child after which we want to skip children
   1336      * @return the number of children to skip, 0 by default
   1337      */
   1338     int getChildrenSkipCount(View child, int index) {
   1339         return 0;
   1340     }
   1341 
   1342     /**
   1343      * <p>Returns the size (width or height) that should be occupied by a null
   1344      * child.</p>
   1345      *
   1346      * @param childIndex the index of the null child
   1347      * @return the width or height of the child depending on the orientation
   1348      */
   1349     int measureNullChild(int childIndex) {
   1350         return 0;
   1351     }
   1352 
   1353     /**
   1354      * <p>Measure the child according to the parent's measure specs. This
   1355      * method should be overriden by subclasses to force the sizing of
   1356      * children. This method is called by {@link #measureVertical(int, int)} and
   1357      * {@link #measureHorizontal(int, int)}.</p>
   1358      *
   1359      * @param child the child to measure
   1360      * @param childIndex the index of the child in this view
   1361      * @param widthMeasureSpec horizontal space requirements as imposed by the parent
   1362      * @param totalWidth extra space that has been used up by the parent horizontally
   1363      * @param heightMeasureSpec vertical space requirements as imposed by the parent
   1364      * @param totalHeight extra space that has been used up by the parent vertically
   1365      */
   1366     void measureChildBeforeLayout(View child, int childIndex,
   1367             int widthMeasureSpec, int totalWidth, int heightMeasureSpec,
   1368             int totalHeight) {
   1369         measureChildWithMargins(child, widthMeasureSpec, totalWidth,
   1370                 heightMeasureSpec, totalHeight);
   1371     }
   1372 
   1373     /**
   1374      * <p>Return the location offset of the specified child. This can be used
   1375      * by subclasses to change the location of a given widget.</p>
   1376      *
   1377      * @param child the child for which to obtain the location offset
   1378      * @return the location offset in pixels
   1379      */
   1380     int getLocationOffset(View child) {
   1381         return 0;
   1382     }
   1383 
   1384     /**
   1385      * <p>Return the size offset of the next sibling of the specified child.
   1386      * This can be used by subclasses to change the location of the widget
   1387      * following <code>child</code>.</p>
   1388      *
   1389      * @param child the child whose next sibling will be moved
   1390      * @return the location offset of the next child in pixels
   1391      */
   1392     int getNextLocationOffset(View child) {
   1393         return 0;
   1394     }
   1395 
   1396     @Override
   1397     protected void onLayout(boolean changed, int l, int t, int r, int b) {
   1398         if (mOrientation == VERTICAL) {
   1399             layoutVertical();
   1400         } else {
   1401             layoutHorizontal();
   1402         }
   1403     }
   1404 
   1405     /**
   1406      * Position the children during a layout pass if the orientation of this
   1407      * LinearLayout is set to {@link #VERTICAL}.
   1408      *
   1409      * @see #getOrientation()
   1410      * @see #setOrientation(int)
   1411      * @see #onLayout(boolean, int, int, int, int)
   1412      */
   1413     void layoutVertical() {
   1414         final int paddingLeft = mPaddingLeft;
   1415 
   1416         int childTop;
   1417         int childLeft;
   1418 
   1419         // Where right end of child should go
   1420         final int width = mRight - mLeft;
   1421         int childRight = width - mPaddingRight;
   1422 
   1423         // Space available for child
   1424         int childSpace = width - paddingLeft - mPaddingRight;
   1425 
   1426         final int count = getVirtualChildCount();
   1427 
   1428         final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
   1429         final int minorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
   1430 
   1431         switch (majorGravity) {
   1432            case Gravity.BOTTOM:
   1433                // mTotalLength contains the padding already
   1434                childTop = mPaddingTop + mBottom - mTop - mTotalLength;
   1435                break;
   1436 
   1437                // mTotalLength contains the padding already
   1438            case Gravity.CENTER_VERTICAL:
   1439                childTop = mPaddingTop + (mBottom - mTop - mTotalLength) / 2;
   1440                break;
   1441 
   1442            case Gravity.TOP:
   1443            default:
   1444                childTop = mPaddingTop;
   1445                break;
   1446         }
   1447 
   1448         for (int i = 0; i < count; i++) {
   1449             final View child = getVirtualChildAt(i);
   1450             if (child == null) {
   1451                 childTop += measureNullChild(i);
   1452             } else if (child.getVisibility() != GONE) {
   1453                 final int childWidth = child.getMeasuredWidth();
   1454                 final int childHeight = child.getMeasuredHeight();
   1455 
   1456                 final LinearLayout.LayoutParams lp =
   1457                         (LinearLayout.LayoutParams) child.getLayoutParams();
   1458 
   1459                 int gravity = lp.gravity;
   1460                 if (gravity < 0) {
   1461                     gravity = minorGravity;
   1462                 }
   1463                 final int layoutDirection = getResolvedLayoutDirection();
   1464                 final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
   1465                 switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
   1466                     case Gravity.CENTER_HORIZONTAL:
   1467                         childLeft = paddingLeft + ((childSpace - childWidth) / 2)
   1468                                 + lp.leftMargin - lp.rightMargin;
   1469                         break;
   1470 
   1471                     case Gravity.RIGHT:
   1472                         childLeft = childRight - childWidth - lp.rightMargin;
   1473                         break;
   1474 
   1475                     case Gravity.LEFT:
   1476                     default:
   1477                         childLeft = paddingLeft + lp.leftMargin;
   1478                         break;
   1479                 }
   1480 
   1481                 if (hasDividerBeforeChildAt(i)) {
   1482                     childTop += mDividerHeight;
   1483                 }
   1484 
   1485                 childTop += lp.topMargin;
   1486                 setChildFrame(child, childLeft, childTop + getLocationOffset(child),
   1487                         childWidth, childHeight);
   1488                 childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);
   1489 
   1490                 i += getChildrenSkipCount(child, i);
   1491             }
   1492         }
   1493     }
   1494 
   1495     /**
   1496      * Position the children during a layout pass if the orientation of this
   1497      * LinearLayout is set to {@link #HORIZONTAL}.
   1498      *
   1499      * @see #getOrientation()
   1500      * @see #setOrientation(int)
   1501      * @see #onLayout(boolean, int, int, int, int)
   1502      */
   1503     void layoutHorizontal() {
   1504         final boolean isLayoutRtl = isLayoutRtl();
   1505         final int paddingTop = mPaddingTop;
   1506 
   1507         int childTop;
   1508         int childLeft;
   1509 
   1510         // Where bottom of child should go
   1511         final int height = mBottom - mTop;
   1512         int childBottom = height - mPaddingBottom;
   1513 
   1514         // Space available for child
   1515         int childSpace = height - paddingTop - mPaddingBottom;
   1516 
   1517         final int count = getVirtualChildCount();
   1518 
   1519         final int majorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
   1520         final int minorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
   1521 
   1522         final boolean baselineAligned = mBaselineAligned;
   1523 
   1524         final int[] maxAscent = mMaxAscent;
   1525         final int[] maxDescent = mMaxDescent;
   1526 
   1527         final int layoutDirection = getResolvedLayoutDirection();
   1528         switch (Gravity.getAbsoluteGravity(majorGravity, layoutDirection)) {
   1529             case Gravity.RIGHT:
   1530                 // mTotalLength contains the padding already
   1531                 childLeft = mPaddingLeft + mRight - mLeft - mTotalLength;
   1532                 break;
   1533 
   1534             case Gravity.CENTER_HORIZONTAL:
   1535                 // mTotalLength contains the padding already
   1536                 childLeft = mPaddingLeft + (mRight - mLeft - mTotalLength) / 2;
   1537                 break;
   1538 
   1539             case Gravity.LEFT:
   1540             default:
   1541                 childLeft = mPaddingLeft;
   1542                 break;
   1543         }
   1544 
   1545         int start = 0;
   1546         int dir = 1;
   1547         //In case of RTL, start drawing from the last child.
   1548         if (isLayoutRtl) {
   1549             start = count - 1;
   1550             dir = -1;
   1551         }
   1552 
   1553         for (int i = 0; i < count; i++) {
   1554             int childIndex = start + dir * i;
   1555             final View child = getVirtualChildAt(childIndex);
   1556 
   1557             if (child == null) {
   1558                 childLeft += measureNullChild(childIndex);
   1559             } else if (child.getVisibility() != GONE) {
   1560                 final int childWidth = child.getMeasuredWidth();
   1561                 final int childHeight = child.getMeasuredHeight();
   1562                 int childBaseline = -1;
   1563 
   1564                 final LinearLayout.LayoutParams lp =
   1565                         (LinearLayout.LayoutParams) child.getLayoutParams();
   1566 
   1567                 if (baselineAligned && lp.height != LayoutParams.MATCH_PARENT) {
   1568                     childBaseline = child.getBaseline();
   1569                 }
   1570 
   1571                 int gravity = lp.gravity;
   1572                 if (gravity < 0) {
   1573                     gravity = minorGravity;
   1574                 }
   1575 
   1576                 switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
   1577                     case Gravity.TOP:
   1578                         childTop = paddingTop + lp.topMargin;
   1579                         if (childBaseline != -1) {
   1580                             childTop += maxAscent[INDEX_TOP] - childBaseline;
   1581                         }
   1582                         break;
   1583 
   1584                     case Gravity.CENTER_VERTICAL:
   1585                         // Removed support for baseline alignment when layout_gravity or
   1586                         // gravity == center_vertical. See bug #1038483.
   1587                         // Keep the code around if we need to re-enable this feature
   1588                         // if (childBaseline != -1) {
   1589                         //     // Align baselines vertically only if the child is smaller than us
   1590                         //     if (childSpace - childHeight > 0) {
   1591                         //         childTop = paddingTop + (childSpace / 2) - childBaseline;
   1592                         //     } else {
   1593                         //         childTop = paddingTop + (childSpace - childHeight) / 2;
   1594                         //     }
   1595                         // } else {
   1596                         childTop = paddingTop + ((childSpace - childHeight) / 2)
   1597                                 + lp.topMargin - lp.bottomMargin;
   1598                         break;
   1599 
   1600                     case Gravity.BOTTOM:
   1601                         childTop = childBottom - childHeight - lp.bottomMargin;
   1602                         if (childBaseline != -1) {
   1603                             int descent = child.getMeasuredHeight() - childBaseline;
   1604                             childTop -= (maxDescent[INDEX_BOTTOM] - descent);
   1605                         }
   1606                         break;
   1607                     default:
   1608                         childTop = paddingTop;
   1609                         break;
   1610                 }
   1611 
   1612                 if (hasDividerBeforeChildAt(childIndex)) {
   1613                     childLeft += mDividerWidth;
   1614                 }
   1615 
   1616                 childLeft += lp.leftMargin;
   1617                 setChildFrame(child, childLeft + getLocationOffset(child), childTop,
   1618                         childWidth, childHeight);
   1619                 childLeft += childWidth + lp.rightMargin +
   1620                         getNextLocationOffset(child);
   1621 
   1622                 i += getChildrenSkipCount(child, childIndex);
   1623             }
   1624         }
   1625     }
   1626 
   1627     private void setChildFrame(View child, int left, int top, int width, int height) {
   1628         child.layout(left, top, left + width, top + height);
   1629     }
   1630 
   1631     /**
   1632      * Should the layout be a column or a row.
   1633      * @param orientation Pass HORIZONTAL or VERTICAL. Default
   1634      * value is HORIZONTAL.
   1635      *
   1636      * @attr ref android.R.styleable#LinearLayout_orientation
   1637      */
   1638     public void setOrientation(int orientation) {
   1639         if (mOrientation != orientation) {
   1640             mOrientation = orientation;
   1641             requestLayout();
   1642         }
   1643     }
   1644 
   1645     /**
   1646      * Returns the current orientation.
   1647      *
   1648      * @return either {@link #HORIZONTAL} or {@link #VERTICAL}
   1649      */
   1650     public int getOrientation() {
   1651         return mOrientation;
   1652     }
   1653 
   1654     /**
   1655      * Describes how the child views are positioned. Defaults to GRAVITY_TOP. If
   1656      * this layout has a VERTICAL orientation, this controls where all the child
   1657      * views are placed if there is extra vertical space. If this layout has a
   1658      * HORIZONTAL orientation, this controls the alignment of the children.
   1659      *
   1660      * @param gravity See {@link android.view.Gravity}
   1661      *
   1662      * @attr ref android.R.styleable#LinearLayout_gravity
   1663      */
   1664     @android.view.RemotableViewMethod
   1665     public void setGravity(int gravity) {
   1666         if (mGravity != gravity) {
   1667             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
   1668                 gravity |= Gravity.START;
   1669             }
   1670 
   1671             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
   1672                 gravity |= Gravity.TOP;
   1673             }
   1674 
   1675             mGravity = gravity;
   1676             requestLayout();
   1677         }
   1678     }
   1679 
   1680     @android.view.RemotableViewMethod
   1681     public void setHorizontalGravity(int horizontalGravity) {
   1682         final int gravity = horizontalGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
   1683         if ((mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) != gravity) {
   1684             mGravity = (mGravity & ~Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) | gravity;
   1685             requestLayout();
   1686         }
   1687     }
   1688 
   1689     @android.view.RemotableViewMethod
   1690     public void setVerticalGravity(int verticalGravity) {
   1691         final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK;
   1692         if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) {
   1693             mGravity = (mGravity & ~Gravity.VERTICAL_GRAVITY_MASK) | gravity;
   1694             requestLayout();
   1695         }
   1696     }
   1697 
   1698     @Override
   1699     public LayoutParams generateLayoutParams(AttributeSet attrs) {
   1700         return new LinearLayout.LayoutParams(getContext(), attrs);
   1701     }
   1702 
   1703     /**
   1704      * Returns a set of layout parameters with a width of
   1705      * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}
   1706      * and a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
   1707      * when the layout's orientation is {@link #VERTICAL}. When the orientation is
   1708      * {@link #HORIZONTAL}, the width is set to {@link LayoutParams#WRAP_CONTENT}
   1709      * and the height to {@link LayoutParams#WRAP_CONTENT}.
   1710      */
   1711     @Override
   1712     protected LayoutParams generateDefaultLayoutParams() {
   1713         if (mOrientation == HORIZONTAL) {
   1714             return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
   1715         } else if (mOrientation == VERTICAL) {
   1716             return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
   1717         }
   1718         return null;
   1719     }
   1720 
   1721     @Override
   1722     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
   1723         return new LayoutParams(p);
   1724     }
   1725 
   1726 
   1727     // Override to allow type-checking of LayoutParams.
   1728     @Override
   1729     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
   1730         return p instanceof LinearLayout.LayoutParams;
   1731     }
   1732 
   1733     /**
   1734      * Per-child layout information associated with ViewLinearLayout.
   1735      *
   1736      * @attr ref android.R.styleable#LinearLayout_Layout_layout_weight
   1737      * @attr ref android.R.styleable#LinearLayout_Layout_layout_gravity
   1738      */
   1739     public static class LayoutParams extends ViewGroup.MarginLayoutParams {
   1740         /**
   1741          * Indicates how much of the extra space in the LinearLayout will be
   1742          * allocated to the view associated with these LayoutParams. Specify
   1743          * 0 if the view should not be stretched. Otherwise the extra pixels
   1744          * will be pro-rated among all views whose weight is greater than 0.
   1745          */
   1746         @ViewDebug.ExportedProperty(category = "layout")
   1747         public float weight;
   1748 
   1749         /**
   1750          * Gravity for the view associated with these LayoutParams.
   1751          *
   1752          * @see android.view.Gravity
   1753          */
   1754         @ViewDebug.ExportedProperty(category = "layout", mapping = {
   1755             @ViewDebug.IntToString(from =  -1,                       to = "NONE"),
   1756             @ViewDebug.IntToString(from = Gravity.NO_GRAVITY,        to = "NONE"),
   1757             @ViewDebug.IntToString(from = Gravity.TOP,               to = "TOP"),
   1758             @ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
   1759             @ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
   1760             @ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
   1761             @ViewDebug.IntToString(from = Gravity.START,            to = "START"),
   1762             @ViewDebug.IntToString(from = Gravity.END,             to = "END"),
   1763             @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
   1764             @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
   1765             @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
   1766             @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL,   to = "FILL_HORIZONTAL"),
   1767             @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
   1768             @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
   1769         })
   1770         public int gravity = -1;
   1771 
   1772         /**
   1773          * {@inheritDoc}
   1774          */
   1775         public LayoutParams(Context c, AttributeSet attrs) {
   1776             super(c, attrs);
   1777             TypedArray a =
   1778                     c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LinearLayout_Layout);
   1779 
   1780             weight = a.getFloat(com.android.internal.R.styleable.LinearLayout_Layout_layout_weight, 0);
   1781             gravity = a.getInt(com.android.internal.R.styleable.LinearLayout_Layout_layout_gravity, -1);
   1782 
   1783             a.recycle();
   1784         }
   1785 
   1786         /**
   1787          * {@inheritDoc}
   1788          */
   1789         public LayoutParams(int width, int height) {
   1790             super(width, height);
   1791             weight = 0;
   1792         }
   1793 
   1794         /**
   1795          * Creates a new set of layout parameters with the specified width, height
   1796          * and weight.
   1797          *
   1798          * @param width the width, either {@link #MATCH_PARENT},
   1799          *        {@link #WRAP_CONTENT} or a fixed size in pixels
   1800          * @param height the height, either {@link #MATCH_PARENT},
   1801          *        {@link #WRAP_CONTENT} or a fixed size in pixels
   1802          * @param weight the weight
   1803          */
   1804         public LayoutParams(int width, int height, float weight) {
   1805             super(width, height);
   1806             this.weight = weight;
   1807         }
   1808 
   1809         /**
   1810          * {@inheritDoc}
   1811          */
   1812         public LayoutParams(ViewGroup.LayoutParams p) {
   1813             super(p);
   1814         }
   1815 
   1816         /**
   1817          * {@inheritDoc}
   1818          */
   1819         public LayoutParams(MarginLayoutParams source) {
   1820             super(source);
   1821         }
   1822 
   1823         @Override
   1824         public String debug(String output) {
   1825             return output + "LinearLayout.LayoutParams={width=" + sizeToString(width) +
   1826                     ", height=" + sizeToString(height) + " weight=" + weight +  "}";
   1827         }
   1828     }
   1829 }
   1830