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