149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/* 249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2014 The Android Open Source Project 349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * you may not use this file except in compliance with the License. 649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * You may obtain a copy of the License at 749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 1049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Unless required by applicable law or agreed to in writing, software 1149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 1249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * See the License for the specific language governing permissions and 1449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * limitations under the License. 1549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 1649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 1749c78900da0d43140fb602431fb93212bd7f6c70Chris Banespackage android.support.v7.widget; 1849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 1949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.content.Context; 2049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.content.res.TypedArray; 2149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.graphics.Canvas; 2249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.graphics.drawable.Drawable; 2349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.os.Build; 2449c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.annotation.IntDef; 2549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.GravityCompat; 2649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.ViewCompat; 2749c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.appcompat.R; 2849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.util.AttributeSet; 2949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.Gravity; 3049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.View; 3149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.ViewGroup; 3249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.accessibility.AccessibilityEvent; 3349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.accessibility.AccessibilityNodeInfo; 3449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 3549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport java.lang.annotation.Retention; 3649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport java.lang.annotation.RetentionPolicy; 3749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 3849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 3949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/** 4049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * A Layout that arranges its children in a single column or a single row. The direction of 4149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the row can be set by calling {@link #setOrientation(int) setOrientation()}. 4249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * You can also specify gravity, which specifies the alignment of all the child elements by 4349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * calling {@link #setGravity(int) setGravity()} or specify that specific children 4449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * grow to fill up any remaining space in the layout by setting the <em>weight</em> member of 4549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link LinearLayoutCompat.LayoutParams LinearLayoutCompat.LayoutParams}. 4649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * The default orientation is horizontal. 4749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 4849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>See the <a href="{@docRoot}guide/topics/ui/layout/linear.html">Linear Layout</a> 4949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * guide.</p> 5049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 5149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p> 52b5837eb1118cfd6e583749bc0a4e72af10c7eb0cChris Banes * Also see {@link LinearLayoutCompat.LayoutParams} for layout attributes </p> 5349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 5449c78900da0d43140fb602431fb93212bd7f6c70Chris Banespublic class LinearLayoutCompat extends ViewGroup { 5549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 5649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @IntDef({HORIZONTAL, VERTICAL}) 5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Retention(RetentionPolicy.SOURCE) 5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public @interface OrientationMode {} 5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 6049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static final int HORIZONTAL = 0; 6149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static final int VERTICAL = 1; 6249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 6349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 6449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @IntDef(flag = true, 6549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes value = { 6649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes SHOW_DIVIDER_NONE, 6749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes SHOW_DIVIDER_BEGINNING, 6849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes SHOW_DIVIDER_MIDDLE, 6949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes SHOW_DIVIDER_END 7049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes }) 7149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Retention(RetentionPolicy.SOURCE) 7249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public @interface DividerMode {} 7349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 7449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 7549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Don't show any dividers. 7649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 7749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static final int SHOW_DIVIDER_NONE = 0; 7849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 7949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Show a divider at the beginning of the group. 8049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 8149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static final int SHOW_DIVIDER_BEGINNING = 1; 8249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 8349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Show dividers between each item in the group. 8449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 8549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static final int SHOW_DIVIDER_MIDDLE = 2; 8649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 8749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Show a divider at the end of the group. 8849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 8949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static final int SHOW_DIVIDER_END = 4; 9049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 9149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 9249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Whether the children of this layout are baseline aligned. Only applicable 9349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * if {@link #mOrientation} is horizontal. 9449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 9549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private boolean mBaselineAligned = true; 9649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 9749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 9849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * If this layout is part of another layout that is baseline aligned, 9949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * use the child at this index as the baseline. 10049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 10149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Note: this is orthogonal to {@link #mBaselineAligned}, which is concerned 10249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * with whether the children of this layout are baseline aligned. 10349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 10449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mBaselineAlignedChildIndex = -1; 10549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 10649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 10749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * The additional offset to the child's baseline. 10849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * We'll calculate the baseline of this layout as we measure vertically; for 10949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * horizontal linear layouts, the offset of 0 is appropriate. 11049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 11149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mBaselineChildTop = 0; 11249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 11349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mOrientation; 11449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 11549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mGravity = GravityCompat.START | Gravity.TOP; 11649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 11749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mTotalLength; 11849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 11949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private float mWeightSum; 12049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 12149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private boolean mUseLargestChild; 12249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 12349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int[] mMaxAscent; 12449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int[] mMaxDescent; 12549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 12649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private static final int VERTICAL_GRAVITY_COUNT = 4; 12749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 12849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private static final int INDEX_CENTER_VERTICAL = 0; 12949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private static final int INDEX_TOP = 1; 13049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private static final int INDEX_BOTTOM = 2; 13149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private static final int INDEX_FILL = 3; 13249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 13349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private Drawable mDivider; 13449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mDividerWidth; 13549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mDividerHeight; 13649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mShowDividers; 13749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mDividerPadding; 13849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 13949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LinearLayoutCompat(Context context) { 14049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes this(context, null); 14149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 14249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 14349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LinearLayoutCompat(Context context, AttributeSet attrs) { 14449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes this(context, attrs, 0); 14549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 14649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 14749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LinearLayoutCompat(Context context, AttributeSet attrs, int defStyleAttr) { 14849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(context, attrs, defStyleAttr); 14949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 150c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes final TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, attrs, 151c497221ee0e2e873f49653ff1a046df2e5276759Chris Banes R.styleable.LinearLayoutCompat, defStyleAttr, 0); 15249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 15349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int index = a.getInt(R.styleable.LinearLayoutCompat_android_orientation, -1); 15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (index >= 0) { 15549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setOrientation(index); 15649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 15749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 15849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes index = a.getInt(R.styleable.LinearLayoutCompat_android_gravity, -1); 15949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (index >= 0) { 16049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setGravity(index); 16149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 16349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean baselineAligned = a.getBoolean(R.styleable.LinearLayoutCompat_android_baselineAligned, true); 16449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!baselineAligned) { 16549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setBaselineAligned(baselineAligned); 16649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 16849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mWeightSum = a.getFloat(R.styleable.LinearLayoutCompat_android_weightSum, -1.0f); 16949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 17049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mBaselineAlignedChildIndex = 17149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes a.getInt(R.styleable.LinearLayoutCompat_android_baselineAlignedChildIndex, -1); 17249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 17349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mUseLargestChild = a.getBoolean(R.styleable.LinearLayoutCompat_measureWithLargestChild, false); 17449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 17549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setDividerDrawable(a.getDrawable(R.styleable.LinearLayoutCompat_divider)); 17649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mShowDividers = a.getInt(R.styleable.LinearLayoutCompat_showDividers, SHOW_DIVIDER_NONE); 17749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayoutCompat_dividerPadding, 0); 17849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 17949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes a.recycle(); 18049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 18149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 18249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 18349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Set how dividers should be shown between items in this layout 18449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 18549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param showDividers One or more of {@link #SHOW_DIVIDER_BEGINNING}, 18649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #SHOW_DIVIDER_MIDDLE}, or {@link #SHOW_DIVIDER_END}, 18749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * or {@link #SHOW_DIVIDER_NONE} to show no dividers. 18849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 18949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setShowDividers(@DividerMode int showDividers) { 19049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (showDividers != mShowDividers) { 19149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes requestLayout(); 19249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mShowDividers = showDividers; 19449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 19549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 19649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 19749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean shouldDelayChildPressedState() { 19849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return false; 19949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 20049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 20149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 20249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return A flag set indicating how dividers should be shown around items. 20349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setShowDividers(int) 20449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 20549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @DividerMode 20649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int getShowDividers() { 20749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mShowDividers; 20849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 20949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 21049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 21149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the divider Drawable that will divide each item. 21249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 21349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setDividerDrawable(Drawable) 21449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 21549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public Drawable getDividerDrawable() { 21649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mDivider; 21749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 21849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 21949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 22049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Set a drawable to be used as a divider between items. 22149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 22249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param divider Drawable that will divide each item. 22349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 22449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setShowDividers(int) 22549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 22649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setDividerDrawable(Drawable divider) { 22749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (divider == mDivider) { 22849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return; 22949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 23049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDivider = divider; 23149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (divider != null) { 23249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDividerWidth = divider.getIntrinsicWidth(); 23349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDividerHeight = divider.getIntrinsicHeight(); 23449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 23549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDividerWidth = 0; 23649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDividerHeight = 0; 23749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 23849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setWillNotDraw(divider == null); 23949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes requestLayout(); 24049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 24149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 24249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 24349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Set padding displayed on both ends of dividers. 24449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 24549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param padding Padding value in pixels that will be applied to each end 24649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 24749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setShowDividers(int) 24849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setDividerDrawable(Drawable) 24949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #getDividerPadding() 25049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 25149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setDividerPadding(int padding) { 25249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDividerPadding = padding; 25349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 25449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 25549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 25649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Get the padding size used to inset dividers in pixels 25749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 25849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setShowDividers(int) 25949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setDividerDrawable(Drawable) 26049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setDividerPadding(int) 26149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 26249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int getDividerPadding() { 26349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mDividerPadding; 26449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 26549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 26649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 26749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Get the width of the current divider drawable. 26849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 26949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @hide Used internally by framework. 27049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 27149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int getDividerWidth() { 27249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mDividerWidth; 27349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 27449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 27549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 27649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected void onDraw(Canvas canvas) { 27749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDivider == null) { 27849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return; 27949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 28049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 28149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mOrientation == VERTICAL) { 28249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes drawDividersVertical(canvas); 28349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 28449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes drawDividersHorizontal(canvas); 28549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 28649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 28749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 28849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void drawDividersVertical(Canvas canvas) { 28949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int count = getVirtualChildCount(); 29049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; i++) { 29149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 29249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 29349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child != null && child.getVisibility() != GONE) { 29449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(i)) { 29549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 29649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int top = child.getTop() - lp.topMargin - mDividerHeight; 29749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes drawHorizontalDivider(canvas, top); 29849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 29949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 30049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 30149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 30249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(count)) { 30349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(count - 1); 30449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int bottom = 0; 30549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 30649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes bottom = getHeight() - getPaddingBottom() - mDividerHeight; 30749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 30849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 30949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes bottom = child.getBottom() + lp.bottomMargin; 31049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 31149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes drawHorizontalDivider(canvas, bottom); 31249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 31349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 31449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 31549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void drawDividersHorizontal(Canvas canvas) { 31649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int count = getVirtualChildCount(); 31749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final boolean isLayoutRtl = ViewUtils.isLayoutRtl(this); 31849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; i++) { 31949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 32049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 32149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child != null && child.getVisibility() != GONE) { 32249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(i)) { 32349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 32449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int position; 32549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isLayoutRtl) { 32649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes position = child.getRight() + lp.rightMargin; 32749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 32849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes position = child.getLeft() - lp.leftMargin - mDividerWidth; 32949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 33049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes drawVerticalDivider(canvas, position); 33149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 33249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 33349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 33449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 33549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(count)) { 33649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(count - 1); 33749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int position; 33849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 33949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isLayoutRtl) { 34049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes position = getPaddingLeft(); 34149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 34249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes position = getWidth() - getPaddingRight() - mDividerWidth; 34349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 34449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 34549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 34649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isLayoutRtl) { 34749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes position = child.getLeft() - lp.leftMargin - mDividerWidth; 34849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 34949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes position = child.getRight() + lp.rightMargin; 35049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 35149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 35249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes drawVerticalDivider(canvas, position); 35349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 35449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 35549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 35649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void drawHorizontalDivider(Canvas canvas, int top) { 35749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDivider.setBounds(getPaddingLeft() + mDividerPadding, top, 35849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight); 35949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDivider.draw(canvas); 36049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 36149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 36249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void drawVerticalDivider(Canvas canvas, int left) { 36349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDivider.setBounds(left, getPaddingTop() + mDividerPadding, 36449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding); 36549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDivider.draw(canvas); 36649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 36749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 36849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 36949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Indicates whether widgets contained within this layout are aligned 37049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * on their baseline or not.</p> 37149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 37249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return true when widgets are baseline-aligned, false otherwise 37349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 37449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean isBaselineAligned() { 37549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mBaselineAligned; 37649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 37749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 37849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 37949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Defines whether widgets contained in this layout are 38049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * baseline-aligned or not.</p> 38149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 38249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param baselineAligned true to align widgets on their baseline, 38349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * false otherwise 38449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 38549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setBaselineAligned(boolean baselineAligned) { 38649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mBaselineAligned = baselineAligned; 38749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 38849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 38949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 39049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * When true, all children with a weight will be considered having 39149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the minimum size of the largest child. If false, all children are 39249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * measured normally. 39349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 39449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return True to measure children with a weight using the minimum 39549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * size of the largest child, false otherwise. 39649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 39749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean isMeasureWithLargestChildEnabled() { 39849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mUseLargestChild; 39949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 40049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 40149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 40249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * When set to true, all children with a weight will be considered having 40349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the minimum size of the largest child. If false, all children are 40449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * measured normally. 40549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 40649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Disabled by default. 40749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 40849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param enabled True to measure children with a weight using the 40949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * minimum size of the largest child, false otherwise. 41049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 41149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setMeasureWithLargestChildEnabled(boolean enabled) { 41249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mUseLargestChild = enabled; 41349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 41449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 41549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 41649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int getBaseline() { 41749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mBaselineAlignedChildIndex < 0) { 41849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return super.getBaseline(); 41949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 42049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 42149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (getChildCount() <= mBaselineAlignedChildIndex) { 42249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes throw new RuntimeException("mBaselineAlignedChildIndex of LinearLayout " 42349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + "set to an index that is out of bounds."); 42449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 42549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 42649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getChildAt(mBaselineAlignedChildIndex); 42749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childBaseline = child.getBaseline(); 42849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 42949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childBaseline == -1) { 43049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mBaselineAlignedChildIndex == 0) { 43149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // this is just the default case, safe to return -1 43249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return -1; 43349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 43449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // the user picked an index that points to something that doesn't 43549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // know how to calculate its baseline. 43649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes throw new RuntimeException("mBaselineAlignedChildIndex of LinearLayout " 43749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + "points to a View that doesn't know how to get its baseline."); 43849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 43949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 44049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // TODO: This should try to take into account the virtual offsets 44149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // (See getNextLocationOffset and getLocationOffset) 44249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // We should add to childTop: 44349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // sum([getNextLocationOffset(getChildAt(i)) / i < mBaselineAlignedChildIndex]) 44449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // and also add: 44549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // getLocationOffset(child) 44649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childTop = mBaselineChildTop; 44749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 44849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mOrientation == VERTICAL) { 44949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK; 45049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (majorGravity != Gravity.TOP) { 45149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes switch (majorGravity) { 45249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.BOTTOM: 45349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = getBottom() - getTop() - getPaddingBottom() - mTotalLength; 45449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 45549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 45649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.CENTER_VERTICAL: 45749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop += ((getBottom() - getTop() - getPaddingTop() - getPaddingBottom()) - 45849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength) / 2; 45949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 46049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 46149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 46249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 46349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 46449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 46549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return childTop + lp.topMargin + childBaseline; 46649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 46749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 46849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 46949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return The index of the child that will be used if this layout is 47049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * part of a larger layout that is baseline aligned, or -1 if none has 47149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * been set. 47249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 47349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int getBaselineAlignedChildIndex() { 47449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mBaselineAlignedChildIndex; 47549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 47649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 47749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 47849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param i The index of the child that will be used if this layout is 47949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * part of a larger layout that is baseline aligned. 48049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 48149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setBaselineAlignedChildIndex(int i) { 48249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((i < 0) || (i >= getChildCount())) { 48349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes throw new IllegalArgumentException("base aligned child index out " 48449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + "of range (0, " + getChildCount() + ")"); 48549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 48649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mBaselineAlignedChildIndex = i; 48749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 48849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 48949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 49049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Returns the view at the specified index. This method can be overriden 49149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to take into account virtual children. Refer to 49249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link android.widget.TableLayout} and {@link android.widget.TableRow} 49349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * for an example.</p> 49449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 49549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param index the child's index 49649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the child at the specified index 49749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 49849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes View getVirtualChildAt(int index) { 49949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return getChildAt(index); 50049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 50149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 50249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 50349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Returns the virtual number of children. This number might be different 50449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * than the actual number of children if the layout can hold virtual 50549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * children. Refer to 50649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link android.widget.TableLayout} and {@link android.widget.TableRow} 50749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * for an example.</p> 50849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 50949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the virtual number of children 51049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 51149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int getVirtualChildCount() { 51249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return getChildCount(); 51349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 51449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 51549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 51649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Returns the desired weights sum. 51749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 51849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return A number greater than 0.0f if the weight sum is defined, or 51949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * a number lower than or equals to 0.0f if not weight sum is 52049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to be used. 52149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 52249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public float getWeightSum() { 52349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mWeightSum; 52449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 52549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 52649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 52749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Defines the desired weights sum. If unspecified the weights sum is computed 52849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * at layout time by adding the layout_weight of each child. 52949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 53049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * This can be used for instance to give a single child 50% of the total 53149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * available space by giving it a layout_weight of 0.5 and setting the 53249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * weightSum to 1.0. 53349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 53449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param weightSum a number greater than 0.0f, or a number lower than or equals 53549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to 0.0f if the weight sum should be computed from the children's 53649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * layout_weight 53749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 53849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setWeightSum(float weightSum) { 53949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mWeightSum = Math.max(0.0f, weightSum); 54049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 54149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 54249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 54349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 54449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mOrientation == VERTICAL) { 54549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes measureVertical(widthMeasureSpec, heightMeasureSpec); 54649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 54749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes measureHorizontal(widthMeasureSpec, heightMeasureSpec); 54849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 54949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 55049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 55149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 55249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Determines where to position dividers between children. 55349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 55449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param childIndex Index of child to check for preceding divider 55549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return true if there should be a divider before the child at childIndex 55649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @hide Pending API consideration. Currently only used internally by the system. 55749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 55849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected boolean hasDividerBeforeChildAt(int childIndex) { 55949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childIndex == 0) { 56049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0; 56149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (childIndex == getChildCount()) { 56249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return (mShowDividers & SHOW_DIVIDER_END) != 0; 56349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) { 56449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean hasVisibleViewBefore = false; 56549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = childIndex - 1; i >= 0; i--) { 56649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (getChildAt(i).getVisibility() != GONE) { 56749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes hasVisibleViewBefore = true; 56849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 56949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 57049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 57149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return hasVisibleViewBefore; 57249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 57349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return false; 57449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 57549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 57649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 57749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Measures the children when the orientation of this LinearLayout is set 57849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to {@link #VERTICAL}. 57949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 58049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param widthMeasureSpec Horizontal space requirements as imposed by the parent. 58149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param heightMeasureSpec Vertical space requirements as imposed by the parent. 58249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 58349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #getOrientation() 58449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setOrientation(int) 58549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #onMeasure(int, int) 58649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 58749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { 58849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = 0; 58949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int maxWidth = 0; 59049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childState = 0; 59149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int alternativeMaxWidth = 0; 59249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int weightedMaxWidth = 0; 59349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean allFillParent = true; 59449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float totalWeight = 0; 59549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 59649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int count = getVirtualChildCount(); 59749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 59849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 59949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 60049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 60149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean matchWidth = false; 60249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean skippedMeasure = false; 60349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 60449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int baselineChildIndex = mBaselineAlignedChildIndex; 60549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final boolean useLargestChild = mUseLargestChild; 60649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 60749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int largestChildHeight = Integer.MIN_VALUE; 60849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 60949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // See how tall everyone is. Also remember max width. 61049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; ++i) { 61149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 61249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 61349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 61449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += measureNullChild(i); 61549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 61649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 61749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 61849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() == View.GONE) { 61949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, i); 62049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 62149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 62249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 62349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(i)) { 62449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += mDividerHeight; 62549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 62649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 62749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 62849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 62949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes totalWeight += lp.weight; 63049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 63149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) { 63249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Optimization: don't bother measuring children who are going to use 63349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // leftover space. These views will get measured again down below if 63449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // there is any leftover space. 63549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 63649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin); 63749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes skippedMeasure = true; 63849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 63949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int oldHeight = Integer.MIN_VALUE; 64049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 64149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.height == 0 && lp.weight > 0) { 64249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // heightMode is either UNSPECIFIED or AT_MOST, and this 64349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child wanted to stretch to fill available space. 64449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Translate that to WRAP_CONTENT so that it does not end up 64549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // with a height of 0 64649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes oldHeight = 0; 64749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.height = LayoutParams.WRAP_CONTENT; 64849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 64949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 65049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Determine how big this child would like to be. If this or 65149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // previous children have given a weight, then we allow it to 65249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // use all available space (and we will shrink things later 65349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // if needed). 65449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes measureChildBeforeLayout( 65549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child, i, widthMeasureSpec, 0, heightMeasureSpec, 65649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes totalWeight == 0 ? mTotalLength : 0); 65749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 65849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (oldHeight != Integer.MIN_VALUE) { 65949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.height = oldHeight; 66049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 66149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 66249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childHeight = child.getMeasuredHeight(); 66349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 66449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin + 66549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.bottomMargin + getNextLocationOffset(child)); 66649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 66749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (useLargestChild) { 66849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes largestChildHeight = Math.max(childHeight, largestChildHeight); 66949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 67049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 67149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 67249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 67349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * If applicable, compute the additional offset to the child's baseline 67449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * we'll need later when asked {@link #getBaseline}. 67549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 67649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((baselineChildIndex >= 0) && (baselineChildIndex == i + 1)) { 67749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mBaselineChildTop = mTotalLength; 67849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 67949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 68049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // if we are trying to use a child index for our baseline, the above 68149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // book keeping only works if there are no children above it with 68249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // weight. fail fast to aid the developer. 68349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (i < baselineChildIndex && lp.weight > 0) { 68449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes throw new RuntimeException("A child of LinearLayout with index " 68549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + "less than mBaselineAlignedChildIndex has weight > 0, which " 68649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + "won't work. Either remove the weight, or don't set " 68749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + "mBaselineAlignedChildIndex."); 68849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 68949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 69049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean matchWidthLocally = false; 69149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.MATCH_PARENT) { 69249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // The width of the linear layout will scale, and at least one 69349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child said it wanted to match our width. Set a flag 69449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // indicating that we need to remeasure at least that view when 69549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // we know our width. 69649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchWidth = true; 69749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchWidthLocally = true; 69849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 69949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 70049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int margin = lp.leftMargin + lp.rightMargin; 70149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int measuredWidth = child.getMeasuredWidth() + margin; 70249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxWidth = Math.max(maxWidth, measuredWidth); 70349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childState = ViewUtils.combineMeasuredStates(childState, 70449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ViewCompat.getMeasuredState(child)); 70549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 70649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT; 70749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.weight > 0) { 70849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /* 70949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Widths of weighted Views are bogus if we end up 71049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * remeasuring, so keep them separate. 71149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 71249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes weightedMaxWidth = Math.max(weightedMaxWidth, 71349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchWidthLocally ? margin : measuredWidth); 71449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 71549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes alternativeMaxWidth = Math.max(alternativeMaxWidth, 71649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchWidthLocally ? margin : measuredWidth); 71749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 71849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 71949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, i); 72049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 72149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 72249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mTotalLength > 0 && hasDividerBeforeChildAt(count)) { 72349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += mDividerHeight; 72449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 72549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 72649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (useLargestChild && 72749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) { 72849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = 0; 72949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 73049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; ++i) { 73149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 73249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 73349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 73449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += measureNullChild(i); 73549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 73649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 73749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 73849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() == GONE) { 73949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, i); 74049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 74149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 74249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 74349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) 74449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.getLayoutParams(); 74549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Account for negative margins 74649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 74749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + largestChildHeight + 74849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.topMargin + lp.bottomMargin + getNextLocationOffset(child)); 74949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 75049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 75149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 75249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Add in our padding 75349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += getPaddingTop() + getPaddingBottom(); 75449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 75549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int heightSize = mTotalLength; 75649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 75749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Check against our minimum height 75849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightSize = Math.max(heightSize, getSuggestedMinimumHeight()); 75949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 76049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Reconcile our calculated size with the heightMeasureSpec 76149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int heightSizeAndState = ViewCompat.resolveSizeAndState(heightSize, heightMeasureSpec, 0); 76249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightSize = heightSizeAndState & ViewCompat.MEASURED_SIZE_MASK; 76349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 76449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Either expand children with weight to take up available space or 76549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // shrink them if they extend beyond our current bounds. If we skipped 76649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // measurement on any children, we need to measure them now. 76749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int delta = heightSize - mTotalLength; 76849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (skippedMeasure || delta != 0 && totalWeight > 0.0f) { 76949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight; 77049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 77149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = 0; 77249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 77349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; ++i) { 77449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 77549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 77649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() == View.GONE) { 77749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 77849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 77949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 78049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 78149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 78249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float childExtra = lp.weight; 78349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childExtra > 0) { 78449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Child said it could absorb extra space -- give him his share 78549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int share = (int) (childExtra * delta / weightSum); 78649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes weightSum -= childExtra; 78749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes delta -= share; 78849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 78949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 79049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes getPaddingLeft() + getPaddingRight() + 79149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.leftMargin + lp.rightMargin, lp.width); 79249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 79349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // TODO: Use a field like lp.isMeasured to figure out if this 79449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child has been previously measured 79549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) { 79649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child was measured once already above... 79749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // base new measurement on stored values 79849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childHeight = child.getMeasuredHeight() + share; 79949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childHeight < 0) { 80049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childHeight = 0; 80149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 80249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 80349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.measure(childWidthMeasureSpec, 80449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY)); 80549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 80649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child was skipped in the loop above. 80749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Measure for this first time here 80849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.measure(childWidthMeasureSpec, 80949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.makeMeasureSpec(share > 0 ? share : 0, 81049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.EXACTLY)); 81149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 81249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 81349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Child may now not fit in vertical dimension. 81449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childState = ViewUtils.combineMeasuredStates(childState, 81549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ViewCompat.getMeasuredState(child) & (ViewCompat.MEASURED_STATE_MASK 81649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes >> ViewCompat.MEASURED_HEIGHT_STATE_SHIFT)); 81749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 81849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 81949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int margin = lp.leftMargin + lp.rightMargin; 82049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int measuredWidth = child.getMeasuredWidth() + margin; 82149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxWidth = Math.max(maxWidth, measuredWidth); 82249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 82349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean matchWidthLocally = widthMode != MeasureSpec.EXACTLY && 82449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.width == LayoutParams.MATCH_PARENT; 82549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 82649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes alternativeMaxWidth = Math.max(alternativeMaxWidth, 82749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchWidthLocally ? margin : measuredWidth); 82849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 82949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT; 83049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 83149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 83249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredHeight() + 83349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.topMargin + lp.bottomMargin + getNextLocationOffset(child)); 83449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 83549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 83649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Add in our padding 83749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += getPaddingTop() + getPaddingBottom(); 83849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // TODO: Should we recompute the heightSpec based on the new total length? 83949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 84049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes alternativeMaxWidth = Math.max(alternativeMaxWidth, 84149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes weightedMaxWidth); 84249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 84349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 84449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // We have no limit, so make all weighted views as tall as the largest child. 84549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Children will have already been measured once. 84649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (useLargestChild && heightMode != MeasureSpec.EXACTLY) { 84749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; i++) { 84849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 84949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 85049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null || child.getVisibility() == View.GONE) { 85149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 85249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 85349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 85449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = 85549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 85649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 85749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float childExtra = lp.weight; 85849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childExtra > 0) { 85949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.measure( 86049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), 86149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.EXACTLY), 86249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.makeMeasureSpec(largestChildHeight, 86349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.EXACTLY)); 86449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 86549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 86649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 86749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 86849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 86949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!allFillParent && widthMode != MeasureSpec.EXACTLY) { 87049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxWidth = alternativeMaxWidth; 87149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 87249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 87349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxWidth += getPaddingLeft() + getPaddingRight(); 87449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 87549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Check against our minimum width 87649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); 87749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 87849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setMeasuredDimension(ViewCompat.resolveSizeAndState(maxWidth, widthMeasureSpec, childState), 87949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightSizeAndState); 88049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 88149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (matchWidth) { 88249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes forceUniformWidth(count, heightMeasureSpec); 88349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 88449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 88549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 88649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private void forceUniformWidth(int count, int heightMeasureSpec) { 88749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Pretend that the linear layout has an exact size. 88849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int uniformMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), 88949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.EXACTLY); 89049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i< count; ++i) { 89149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 89249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() != GONE) { 89349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes LinearLayoutCompat.LayoutParams lp = ((LinearLayoutCompat.LayoutParams)child.getLayoutParams()); 89449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 89549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.width == LayoutParams.MATCH_PARENT) { 89649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Temporarily force children to reuse their old measured height 89749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // FIXME: this may not be right for something like wrapping text? 89849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int oldHeight = lp.height; 89949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.height = child.getMeasuredHeight(); 90049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 90149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Remeasue with new dimensions 90249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes measureChildWithMargins(child, uniformMeasureSpec, 0, heightMeasureSpec, 0); 90349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.height = oldHeight; 90449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 90549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 90649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 90749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 90849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 90949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 91049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Measures the children when the orientation of this LinearLayout is set 91149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to {@link #HORIZONTAL}. 91249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 91349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param widthMeasureSpec Horizontal space requirements as imposed by the parent. 91449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param heightMeasureSpec Vertical space requirements as imposed by the parent. 91549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 91649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #getOrientation() 91749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setOrientation(int) 91849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #onMeasure(int, int) 91949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 92049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) { 92149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = 0; 92249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int maxHeight = 0; 92349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childState = 0; 92449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int alternativeMaxHeight = 0; 92549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int weightedMaxHeight = 0; 92649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean allFillParent = true; 92749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float totalWeight = 0; 92849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 92949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int count = getVirtualChildCount(); 93049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 93149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 93249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 93349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 93449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean matchHeight = false; 93549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean skippedMeasure = false; 93649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 93749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mMaxAscent == null || mMaxDescent == null) { 93849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mMaxAscent = new int[VERTICAL_GRAVITY_COUNT]; 93949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mMaxDescent = new int[VERTICAL_GRAVITY_COUNT]; 94049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 94149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 94249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int[] maxAscent = mMaxAscent; 94349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int[] maxDescent = mMaxDescent; 94449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 94549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1; 94649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1; 94749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 94849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final boolean baselineAligned = mBaselineAligned; 94949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final boolean useLargestChild = mUseLargestChild; 95049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 95149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final boolean isExactly = widthMode == MeasureSpec.EXACTLY; 95249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 95349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int largestChildWidth = Integer.MIN_VALUE; 95449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 95549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // See how wide everyone is. Also remember max height. 95649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; ++i) { 95749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 95849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 95949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 96049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += measureNullChild(i); 96149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 96249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 96349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 96449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() == GONE) { 96549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, i); 96649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 96749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 96849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 96949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(i)) { 97049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += mDividerWidth; 97149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 97249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 97349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) 97449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.getLayoutParams(); 97549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 97649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes totalWeight += lp.weight; 97749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 97849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) { 97949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Optimization: don't bother measuring children who are going to use 98049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // leftover space. These views will get measured again down below if 98149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // there is any leftover space. 98249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isExactly) { 98349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += lp.leftMargin + lp.rightMargin; 98449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 98549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 98649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + 98749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.leftMargin + lp.rightMargin); 98849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 98949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 99049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Baseline alignment requires to measure widgets to obtain the 99149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // baseline offset (in particular for TextViews). The following 99249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // defeats the optimization mentioned above. Allow the child to 99349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // use as much space as it wants because we can shrink things 99449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // later (and re-measure). 99549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (baselineAligned) { 99649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 99749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.measure(freeSpec, freeSpec); 99849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 99949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes skippedMeasure = true; 100049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 100149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 100249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int oldWidth = Integer.MIN_VALUE; 100349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 100449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.width == 0 && lp.weight > 0) { 100549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // widthMode is either UNSPECIFIED or AT_MOST, and this 100649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child 100749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // wanted to stretch to fill available space. Translate that to 100849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // WRAP_CONTENT so that it does not end up with a width of 0 100949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes oldWidth = 0; 101049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.width = LayoutParams.WRAP_CONTENT; 101149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 101249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 101349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Determine how big this child would like to be. If this or 101449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // previous children have given a weight, then we allow it to 101549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // use all available space (and we will shrink things later 101649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // if needed). 101749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes measureChildBeforeLayout(child, i, widthMeasureSpec, 101849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes totalWeight == 0 ? mTotalLength : 0, 101949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightMeasureSpec, 0); 102049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 102149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (oldWidth != Integer.MIN_VALUE) { 102249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.width = oldWidth; 102349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 102449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 102549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childWidth = child.getMeasuredWidth(); 102649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isExactly) { 102749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += childWidth + lp.leftMargin + lp.rightMargin + 102849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes getNextLocationOffset(child); 102949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 103049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 103149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin + 103249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.rightMargin + getNextLocationOffset(child)); 103349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 103449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 103549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (useLargestChild) { 103649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes largestChildWidth = Math.max(childWidth, largestChildWidth); 103749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 103849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 103949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 104049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean matchHeightLocally = false; 104149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (heightMode != MeasureSpec.EXACTLY && lp.height == LayoutParams.MATCH_PARENT) { 104249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // The height of the linear layout will scale, and at least one 104349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child said it wanted to match our height. Set a flag indicating that 104449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // we need to remeasure at least that view when we know our height. 104549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchHeight = true; 104649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchHeightLocally = true; 104749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 104849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 104949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int margin = lp.topMargin + lp.bottomMargin; 105049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childHeight = child.getMeasuredHeight() + margin; 105149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childState = ViewUtils.combineMeasuredStates(childState, 105249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ViewCompat.getMeasuredState(child)); 105349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 105449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (baselineAligned) { 105549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childBaseline = child.getBaseline(); 105649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childBaseline != -1) { 105749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Translates the child's vertical gravity into an index 105849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // in the range 0..VERTICAL_GRAVITY_COUNT 105949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity) 106049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes & Gravity.VERTICAL_GRAVITY_MASK; 106149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int index = ((gravity >> Gravity.AXIS_Y_SHIFT) 106249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes & ~Gravity.AXIS_SPECIFIED) >> 1; 106349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 106449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[index] = Math.max(maxAscent[index], childBaseline); 106549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxDescent[index] = Math.max(maxDescent[index], childHeight - childBaseline); 106649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 106749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 106849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 106949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight = Math.max(maxHeight, childHeight); 107049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 107149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT; 107249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.weight > 0) { 107349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /* 107449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Heights of weighted Views are bogus if we end up 107549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * remeasuring, so keep them separate. 107649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 107749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes weightedMaxHeight = Math.max(weightedMaxHeight, 107849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchHeightLocally ? margin : childHeight); 107949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 108049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes alternativeMaxHeight = Math.max(alternativeMaxHeight, 108149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchHeightLocally ? margin : childHeight); 108249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 108349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 108449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, i); 108549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 108649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 108749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mTotalLength > 0 && hasDividerBeforeChildAt(count)) { 108849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += mDividerWidth; 108949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 109049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 109149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP, 109249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // the most common case 109349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (maxAscent[INDEX_TOP] != -1 || 109449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[INDEX_CENTER_VERTICAL] != -1 || 109549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[INDEX_BOTTOM] != -1 || 109649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[INDEX_FILL] != -1) { 109749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int ascent = Math.max(maxAscent[INDEX_FILL], 109849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxAscent[INDEX_CENTER_VERTICAL], 109949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM]))); 110049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int descent = Math.max(maxDescent[INDEX_FILL], 110149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxDescent[INDEX_CENTER_VERTICAL], 110249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM]))); 110349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight = Math.max(maxHeight, ascent + descent); 110449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 110549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 110649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (useLargestChild && 110749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED)) { 110849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = 0; 110949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 111049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; ++i) { 111149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 111249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 111349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 111449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += measureNullChild(i); 111549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 111649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 111749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 111849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() == GONE) { 111949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, i); 112049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 112149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 112249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 112349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) 112449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.getLayoutParams(); 112549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isExactly) { 112649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += largestChildWidth + lp.leftMargin + lp.rightMargin + 112749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes getNextLocationOffset(child); 112849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 112949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 113049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + largestChildWidth + 113149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.leftMargin + lp.rightMargin + getNextLocationOffset(child)); 113249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 113349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 113449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 113549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 113649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Add in our padding 113749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += getPaddingLeft() + getPaddingRight(); 113849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 113949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int widthSize = mTotalLength; 114049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 114149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Check against our minimum width 114249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes widthSize = Math.max(widthSize, getSuggestedMinimumWidth()); 114349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 114449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Reconcile our calculated size with the widthMeasureSpec 114549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int widthSizeAndState = ViewCompat.resolveSizeAndState(widthSize, widthMeasureSpec, 0); 114649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes widthSize = widthSizeAndState & ViewCompat.MEASURED_SIZE_MASK; 114749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 114849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Either expand children with weight to take up available space or 114949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // shrink them if they extend beyond our current bounds. If we skipped 115049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // measurement on any children, we need to measure them now. 115149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int delta = widthSize - mTotalLength; 115249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (skippedMeasure || delta != 0 && totalWeight > 0.0f) { 115349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight; 115449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 115549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1; 115649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1; 115749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight = -1; 115849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 115949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = 0; 116049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 116149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; ++i) { 116249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 116349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 116449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null || child.getVisibility() == View.GONE) { 116549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 116649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 116749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 116849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = 116949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 117049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 117149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float childExtra = lp.weight; 117249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childExtra > 0) { 117349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Child said it could absorb extra space -- give him his share 117449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int share = (int) (childExtra * delta / weightSum); 117549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes weightSum -= childExtra; 117649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes delta -= share; 117749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 117849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childHeightMeasureSpec = getChildMeasureSpec( 117949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightMeasureSpec, 118049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, 118149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.height); 118249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 118349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // TODO: Use a field like lp.isMeasured to figure out if this 118449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child has been previously measured 118549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) { 118649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child was measured once already above ... base new measurement 118749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // on stored values 118849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childWidth = child.getMeasuredWidth() + share; 118949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childWidth < 0) { 119049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childWidth = 0; 119149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 119249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 119349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.measure( 119449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), 119549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childHeightMeasureSpec); 119649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 119749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // child was skipped in the loop above. Measure for this first time here 119849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.measure(MeasureSpec.makeMeasureSpec( 119949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes share > 0 ? share : 0, MeasureSpec.EXACTLY), 120049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childHeightMeasureSpec); 120149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 120249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 120349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Child may now not fit in horizontal dimension. 120449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childState = ViewUtils.combineMeasuredStates(childState, 120549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ViewCompat.getMeasuredState(child) & ViewCompat.MEASURED_STATE_MASK); 120649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 120749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 120849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isExactly) { 120949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin + 121049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes getNextLocationOffset(child); 121149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 121249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int totalLength = mTotalLength; 121349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredWidth() + 121449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.leftMargin + lp.rightMargin + getNextLocationOffset(child)); 121549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 121649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 121749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean matchHeightLocally = heightMode != MeasureSpec.EXACTLY && 121849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.height == LayoutParams.MATCH_PARENT; 121949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 122049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int margin = lp.topMargin + lp .bottomMargin; 122149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childHeight = child.getMeasuredHeight() + margin; 122249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight = Math.max(maxHeight, childHeight); 122349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes alternativeMaxHeight = Math.max(alternativeMaxHeight, 122449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes matchHeightLocally ? margin : childHeight); 122549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 122649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT; 122749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 122849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (baselineAligned) { 122949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childBaseline = child.getBaseline(); 123049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childBaseline != -1) { 123149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Translates the child's vertical gravity into an index in the range 0..2 123249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity) 123349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes & Gravity.VERTICAL_GRAVITY_MASK; 123449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int index = ((gravity >> Gravity.AXIS_Y_SHIFT) 123549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes & ~Gravity.AXIS_SPECIFIED) >> 1; 123649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 123749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[index] = Math.max(maxAscent[index], childBaseline); 123849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxDescent[index] = Math.max(maxDescent[index], 123949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childHeight - childBaseline); 124049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 124149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 124249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 124349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 124449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Add in our padding 124549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mTotalLength += getPaddingLeft() + getPaddingRight(); 124649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // TODO: Should we update widthSize with the new total length? 124749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 124849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP, 124949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // the most common case 125049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (maxAscent[INDEX_TOP] != -1 || 125149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[INDEX_CENTER_VERTICAL] != -1 || 125249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[INDEX_BOTTOM] != -1 || 125349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxAscent[INDEX_FILL] != -1) { 125449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int ascent = Math.max(maxAscent[INDEX_FILL], 125549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxAscent[INDEX_CENTER_VERTICAL], 125649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM]))); 125749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int descent = Math.max(maxDescent[INDEX_FILL], 125849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxDescent[INDEX_CENTER_VERTICAL], 125949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM]))); 126049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight = Math.max(maxHeight, ascent + descent); 126149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 126249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 126349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes alternativeMaxHeight = Math.max(alternativeMaxHeight, weightedMaxHeight); 126449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 126549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // We have no limit, so make all weighted views as wide as the largest child. 126649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Children will have already been measured once. 126749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (useLargestChild && widthMode != MeasureSpec.EXACTLY) { 126849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; i++) { 126949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 127049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 127149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null || child.getVisibility() == View.GONE) { 127249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes continue; 127349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 127449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 127549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = 127649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 127749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 127849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes float childExtra = lp.weight; 127949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childExtra > 0) { 128049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.measure( 128149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.makeMeasureSpec(largestChildWidth, MeasureSpec.EXACTLY), 128249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), 128349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.EXACTLY)); 128449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 128549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 128649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 128749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 128849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 128949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!allFillParent && heightMode != MeasureSpec.EXACTLY) { 129049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight = alternativeMaxHeight; 129149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 129249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 129349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight += getPaddingTop() + getPaddingBottom(); 129449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 129549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Check against our minimum height 129649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); 129749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 129849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setMeasuredDimension(widthSizeAndState | (childState&ViewCompat.MEASURED_STATE_MASK), 129949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ViewCompat.resolveSizeAndState(maxHeight, heightMeasureSpec, 130049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (childState<<ViewCompat.MEASURED_HEIGHT_STATE_SHIFT))); 130149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 130249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (matchHeight) { 130349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes forceUniformHeight(count, widthMeasureSpec); 130449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 130549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 130649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 130749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private void forceUniformHeight(int count, int widthMeasureSpec) { 130849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Pretend that the linear layout has an exact size. This is the measured height of 130949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // ourselves. The measured height should be the max height of the children, changed 131049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // to accommodate the heightMeasureSpec from the parent 131149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int uniformMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), 131249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MeasureSpec.EXACTLY); 131349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; ++i) { 131449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 131549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() != GONE) { 131649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 131749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 131849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.height == LayoutParams.MATCH_PARENT) { 131949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Temporarily force children to reuse their old measured width 132049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // FIXME: this may not be right for something like wrapping text? 132149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int oldWidth = lp.width; 132249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.width = child.getMeasuredWidth(); 132349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 132449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Remeasure with new dimensions 132549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes measureChildWithMargins(child, widthMeasureSpec, 0, uniformMeasureSpec, 0); 132649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes lp.width = oldWidth; 132749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 132849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 132949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 133049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 133149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 133249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 133349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Returns the number of children to skip after measuring/laying out 133449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the specified child.</p> 133549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 133649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param child the child after which we want to skip children 133749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param index the index of the child after which we want to skip children 133849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the number of children to skip, 0 by default 133949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 134049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int getChildrenSkipCount(View child, int index) { 134149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return 0; 134249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 134349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 134449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 134549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Returns the size (width or height) that should be occupied by a null 134649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * child.</p> 134749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 134849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param childIndex the index of the null child 134949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the width or height of the child depending on the orientation 135049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 135149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int measureNullChild(int childIndex) { 135249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return 0; 135349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 135449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 135549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 135649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Measure the child according to the parent's measure specs. This 135749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * method should be overriden by subclasses to force the sizing of 135849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * children. This method is called by {@link #measureVertical(int, int)} and 135949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #measureHorizontal(int, int)}.</p> 136049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 136149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param child the child to measure 136249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param childIndex the index of the child in this view 136349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param widthMeasureSpec horizontal space requirements as imposed by the parent 136449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param totalWidth extra space that has been used up by the parent horizontally 136549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param heightMeasureSpec vertical space requirements as imposed by the parent 136649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param totalHeight extra space that has been used up by the parent vertically 136749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 136849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void measureChildBeforeLayout(View child, int childIndex, 136949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int widthMeasureSpec, int totalWidth, int heightMeasureSpec, 137049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int totalHeight) { 137149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes measureChildWithMargins(child, widthMeasureSpec, totalWidth, 137249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightMeasureSpec, totalHeight); 137349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 137449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 137549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 137649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Return the location offset of the specified child. This can be used 137749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * by subclasses to change the location of a given widget.</p> 137849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 137949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param child the child for which to obtain the location offset 138049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the location offset in pixels 138149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 138249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int getLocationOffset(View child) { 138349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return 0; 138449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 138549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 138649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 138749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Return the size offset of the next sibling of the specified child. 138849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * This can be used by subclasses to change the location of the widget 138949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * following <code>child</code>.</p> 139049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 139149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param child the child whose next sibling will be moved 139249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the location offset of the next child in pixels 139349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 139449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int getNextLocationOffset(View child) { 139549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return 0; 139649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 139749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 139849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 139949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected void onLayout(boolean changed, int l, int t, int r, int b) { 140049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mOrientation == VERTICAL) { 140149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes layoutVertical(l, t, r, b); 140249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 140349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes layoutHorizontal(l, t, r, b); 140449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 140549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 140649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 140749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 140849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Position the children during a layout pass if the orientation of this 140949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * LinearLayout is set to {@link #VERTICAL}. 141049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 141149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #getOrientation() 141249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setOrientation(int) 141349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #onLayout(boolean, int, int, int, int) 141449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param left 141549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param top 141649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param right 141749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param bottom 141849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 141949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void layoutVertical(int left, int top, int right, int bottom) { 142049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int paddingLeft = getPaddingLeft(); 142149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 142249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childTop; 142349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childLeft; 142449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 142549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Where right end of child should go 142649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int width = right - left; 142749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childRight = width - getPaddingRight(); 142849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 142949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Space available for child 143049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childSpace = width - paddingLeft - getPaddingRight(); 143149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 143249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int count = getVirtualChildCount(); 143349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 143449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK; 143549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int minorGravity = mGravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK; 143649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 143749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes switch (majorGravity) { 143849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.BOTTOM: 143949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // mTotalLength contains the padding already 144049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = getPaddingTop() + bottom - top - mTotalLength; 144149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 144249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 144349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // mTotalLength contains the padding already 144449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.CENTER_VERTICAL: 144549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = getPaddingTop() + (bottom - top - mTotalLength) / 2; 144649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 144749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 144849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.TOP: 144949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes default: 145049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = getPaddingTop(); 145149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 145249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 145349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 145449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; i++) { 145549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(i); 145649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 145749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop += measureNullChild(i); 145849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (child.getVisibility() != GONE) { 145949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childWidth = child.getMeasuredWidth(); 146049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childHeight = child.getMeasuredHeight(); 146149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 146249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = 146349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 146449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 146549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int gravity = lp.gravity; 146649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (gravity < 0) { 146749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes gravity = minorGravity; 146849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 146949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int layoutDirection = ViewCompat.getLayoutDirection(this); 147049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int absoluteGravity = GravityCompat.getAbsoluteGravity(gravity, 147149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes layoutDirection); 147249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { 147349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.CENTER_HORIZONTAL: 147449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft = paddingLeft + ((childSpace - childWidth) / 2) 147549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + lp.leftMargin - lp.rightMargin; 147649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 147749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 147849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.RIGHT: 147949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft = childRight - childWidth - lp.rightMargin; 148049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 148149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 148249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.LEFT: 148349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes default: 148449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft = paddingLeft + lp.leftMargin; 148549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 148649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 148749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 148849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(i)) { 148949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop += mDividerHeight; 149049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 149149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 149249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop += lp.topMargin; 149349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setChildFrame(child, childLeft, childTop + getLocationOffset(child), 149449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childWidth, childHeight); 149549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child); 149649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 149749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, i); 149849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 149949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 150049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 150149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 150249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 150349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Position the children during a layout pass if the orientation of this 150449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * LinearLayout is set to {@link #HORIZONTAL}. 150549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 150649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #getOrientation() 150749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setOrientation(int) 150849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #onLayout(boolean, int, int, int, int) 150949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param left 151049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param top 151149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param right 151249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param bottom 151349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 151449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes void layoutHorizontal(int left, int top, int right, int bottom) { 151549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final boolean isLayoutRtl = ViewUtils.isLayoutRtl(this); 151649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int paddingTop = getPaddingTop(); 151749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 151849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childTop; 151949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childLeft; 152049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 152149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Where bottom of child should go 152249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int height = bottom - top; 152349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childBottom = height - getPaddingBottom(); 152449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 152549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Space available for child 152649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childSpace = height - paddingTop - getPaddingBottom(); 152749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 152849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int count = getVirtualChildCount(); 152949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 153049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int majorGravity = mGravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK; 153149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int minorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK; 153249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 153349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final boolean baselineAligned = mBaselineAligned; 153449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 153549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int[] maxAscent = mMaxAscent; 153649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int[] maxDescent = mMaxDescent; 153749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 153849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int layoutDirection = ViewCompat.getLayoutDirection(this); 153949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes switch (GravityCompat.getAbsoluteGravity(majorGravity, layoutDirection)) { 154049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.RIGHT: 154149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // mTotalLength contains the padding already 154249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft = getPaddingLeft() + right - left - mTotalLength; 154349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 154449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 154549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.CENTER_HORIZONTAL: 154649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // mTotalLength contains the padding already 154749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft = getPaddingLeft() + (right - left - mTotalLength) / 2; 154849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 154949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 155049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.LEFT: 155149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes default: 155249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft = getPaddingLeft(); 155349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 155449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 155549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 155649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int start = 0; 155749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int dir = 1; 155849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes //In case of RTL, start drawing from the last child. 155949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (isLayoutRtl) { 156049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes start = count - 1; 156149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes dir = -1; 156249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 156349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 156449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes for (int i = 0; i < count; i++) { 156549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childIndex = start + dir * i; 156649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View child = getVirtualChildAt(childIndex); 156749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 156849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child == null) { 156949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft += measureNullChild(childIndex); 157049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (child.getVisibility() != GONE) { 157149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childWidth = child.getMeasuredWidth(); 157249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childHeight = child.getMeasuredHeight(); 157349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int childBaseline = -1; 157449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 157549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LinearLayoutCompat.LayoutParams lp = 157649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); 157749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 157849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (baselineAligned && lp.height != LayoutParams.MATCH_PARENT) { 157949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childBaseline = child.getBaseline(); 158049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 158149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 158249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int gravity = lp.gravity; 158349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (gravity < 0) { 158449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes gravity = minorGravity; 158549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 158649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 158749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) { 158849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.TOP: 158949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = paddingTop + lp.topMargin; 159049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childBaseline != -1) { 159149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop += maxAscent[INDEX_TOP] - childBaseline; 159249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 159349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 159449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 159549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.CENTER_VERTICAL: 159649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Removed support for baseline alignment when layout_gravity or 159749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // gravity == center_vertical. See bug #1038483. 159849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Keep the code around if we need to re-enable this feature 159949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // if (childBaseline != -1) { 160049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // // Align baselines vertically only if the child is smaller than us 160149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // if (childSpace - childHeight > 0) { 160249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // childTop = paddingTop + (childSpace / 2) - childBaseline; 160349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // } else { 160449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // childTop = paddingTop + (childSpace - childHeight) / 2; 160549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // } 160649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // } else { 160749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = paddingTop + ((childSpace - childHeight) / 2) 160849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes + lp.topMargin - lp.bottomMargin; 160949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 161049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 161149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes case Gravity.BOTTOM: 161249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = childBottom - childHeight - lp.bottomMargin; 161349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childBaseline != -1) { 161449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int descent = child.getMeasuredHeight() - childBaseline; 161549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop -= (maxDescent[INDEX_BOTTOM] - descent); 161649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 161749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 161849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes default: 161949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childTop = paddingTop; 162049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes break; 162149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 162249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 162349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasDividerBeforeChildAt(childIndex)) { 162449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft += mDividerWidth; 162549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 162649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 162749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft += lp.leftMargin; 162849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setChildFrame(child, childLeft + getLocationOffset(child), childTop, 162949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childWidth, childHeight); 163049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes childLeft += childWidth + lp.rightMargin + 163149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes getNextLocationOffset(child); 163249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 163349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes i += getChildrenSkipCount(child, childIndex); 163449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 163549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 163649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 163749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 163849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private void setChildFrame(View child, int left, int top, int width, int height) { 163949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes child.layout(left, top, left + width, top + height); 164049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 164149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 164249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 164349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Should the layout be a column or a row. 164449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param orientation Pass {@link #HORIZONTAL} or {@link #VERTICAL}. Default 164549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * value is {@link #HORIZONTAL}. 164649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 164749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setOrientation(@OrientationMode int orientation) { 164849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mOrientation != orientation) { 164949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mOrientation = orientation; 165049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes requestLayout(); 165149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 165249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 165349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 165449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 165549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Returns the current orientation. 165649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 165749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return either {@link #HORIZONTAL} or {@link #VERTICAL} 165849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 165949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @OrientationMode 166049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int getOrientation() { 166149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mOrientation; 166249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 166349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 166449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 166549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Describes how the child views are positioned. Defaults to GRAVITY_TOP. If 166649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * this layout has a VERTICAL orientation, this controls where all the child 166749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * views are placed if there is extra vertical space. If this layout has a 166849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * HORIZONTAL orientation, this controls the alignment of the children. 166949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 167049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param gravity See {@link android.view.Gravity} 167149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 167249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setGravity(int gravity) { 167349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mGravity != gravity) { 167449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((gravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { 167549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes gravity |= GravityCompat.START; 167649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 167749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 167849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { 167949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes gravity |= Gravity.TOP; 168049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 168149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 168249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mGravity = gravity; 168349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes requestLayout(); 168449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 168549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 168649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 168749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setHorizontalGravity(int horizontalGravity) { 168849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int gravity = horizontalGravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK; 168949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((mGravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK) != gravity) { 169049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mGravity = (mGravity & ~GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK) | gravity; 169149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes requestLayout(); 169249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 169349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 169449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 169549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setVerticalGravity(int verticalGravity) { 169649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK; 169749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) { 169849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mGravity = (mGravity & ~Gravity.VERTICAL_GRAVITY_MASK) | gravity; 169949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes requestLayout(); 170049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 170149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 170249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 170349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 170449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams generateLayoutParams(AttributeSet attrs) { 170549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return new LinearLayoutCompat.LayoutParams(getContext(), attrs); 170649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 170749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 170849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 170949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Returns a set of layout parameters with a width of 171049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} 171149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * and a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} 171249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * when the layout's orientation is {@link #VERTICAL}. When the orientation is 171349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #HORIZONTAL}, the width is set to {@link LayoutParams#WRAP_CONTENT} 171449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * and the height to {@link LayoutParams#WRAP_CONTENT}. 171549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 171649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 171749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected LayoutParams generateDefaultLayoutParams() { 171849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mOrientation == HORIZONTAL) { 171949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 172049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (mOrientation == VERTICAL) { 172149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 172249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 172349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return null; 172449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 172549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 172649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 172749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 172849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return new LayoutParams(p); 172949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 173049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 173149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 173249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Override to allow type-checking of LayoutParams. 173349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 173449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 173549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return p instanceof LinearLayoutCompat.LayoutParams; 173649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 173749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 173849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 173949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (Build.VERSION.SDK_INT >= 14) { 174049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super.onInitializeAccessibilityEvent(event); 174149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes event.setClassName(LinearLayoutCompat.class.getName()); 174249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 174349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 174449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 174549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 174649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (Build.VERSION.SDK_INT >= 14) { 174749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super.onInitializeAccessibilityNodeInfo(info); 174849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes info.setClassName(LinearLayoutCompat.class.getName()); 174949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 175049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 175149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 175249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 175349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Per-child layout information associated with ViewLinearLayout. 175449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 175549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static class LayoutParams extends ViewGroup.MarginLayoutParams { 175649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 175749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Indicates how much of the extra space in the LinearLayout will be 175849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * allocated to the view associated with these LayoutParams. Specify 175949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 0 if the view should not be stretched. Otherwise the extra pixels 176049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * will be pro-rated among all views whose weight is greater than 0. 176149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 176249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public float weight; 176349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 176449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 176549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Gravity for the view associated with these LayoutParams. 176649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 176749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see android.view.Gravity 176849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 176949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int gravity = -1; 177049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 177149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 177249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@inheritDoc} 177349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 177449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams(Context c, AttributeSet attrs) { 177549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(c, attrs); 177649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes TypedArray a = 177749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes c.obtainStyledAttributes(attrs, R.styleable.LinearLayoutCompat_Layout); 177849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 177949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes weight = a.getFloat(R.styleable.LinearLayoutCompat_Layout_android_layout_weight, 0); 178049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes gravity = a.getInt(R.styleable.LinearLayoutCompat_Layout_android_layout_gravity, -1); 178149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 178249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes a.recycle(); 178349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 178449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 178549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 178649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@inheritDoc} 178749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 178849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams(int width, int height) { 178949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(width, height); 179049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes weight = 0; 179149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 179249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 179349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 179449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Creates a new set of layout parameters with the specified width, height 179549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * and weight. 179649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 179749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param width the width, either {@link #MATCH_PARENT}, 179849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #WRAP_CONTENT} or a fixed size in pixels 179949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param height the height, either {@link #MATCH_PARENT}, 180049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #WRAP_CONTENT} or a fixed size in pixels 180149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param weight the weight 180249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 180349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams(int width, int height, float weight) { 180449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(width, height); 180549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes this.weight = weight; 180649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 180749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 180849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 180949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@inheritDoc} 181049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 181149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams(ViewGroup.LayoutParams p) { 181249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(p); 181349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 181449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 181549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 181649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@inheritDoc} 181749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 181849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams(ViewGroup.MarginLayoutParams source) { 181949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(source); 182049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 182149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 182249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 182349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copy constructor. Clones the width, height, margin values, weight, 182449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * and gravity of the source. 182549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 182649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param source The layout params to copy from. 182749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 182849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams(LayoutParams source) { 182949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(source); 183049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 183149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes this.weight = source.weight; 183249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes this.gravity = source.gravity; 183349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 183449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 18356da3e2ee07ff8acd7de4ed810eafeb70a8d4027dChris Banes} 1836