RelativeLayout.java revision 6876b4fb9082fe525d6edb59a834bb0e7c35ca39
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
196876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guyimport android.util.ArrayMap;
209e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglioimport com.android.internal.R;
219e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglio
22bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guyimport java.util.ArrayDeque;
239e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglioimport java.util.ArrayList;
249e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglioimport java.util.Comparator;
259e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglioimport java.util.SortedSet;
269e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglioimport java.util.TreeSet;
279e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglio
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
296a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglioimport android.content.res.TypedArray;
3075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.graphics.Rect;
317da4b73a236b7c72d1337696949df7a00776dd06Adam Powellimport android.os.Build;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
336876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guyimport android.util.Pools.SynchronizedPool;
346a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglioimport android.util.SparseArray;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity;
3675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.view.View;
37c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.view.ViewDebug;
3875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.view.ViewGroup;
3975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.view.accessibility.AccessibilityEvent;
408a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.RemoteViews.RemoteView;
426a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio
43c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglioimport static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Layout where the positions of the children can be described in relation to each other or to the
47520c4204fb9d4f2a7a79dcb5d171e681b7bc6a07Romain Guy * parent.
48a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy *
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note that you cannot have a circular dependency between the size of the RelativeLayout and the
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * position of its children. For example, you cannot have a RelativeLayout whose height is set to
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} and a child set to
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #ALIGN_PARENT_BOTTOM}.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p>
55a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy *
562c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * <p><strong>Note:</strong> In platform version 17 and lower, RelativeLayout was affected by
572c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * a measurement bug that could cause child views to be measured with incorrect
582c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * {@link android.view.View.MeasureSpec MeasureSpec} values. (See
592c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * {@link android.view.View.MeasureSpec#makeMeasureSpec(int, int) MeasureSpec.makeMeasureSpec}
602c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * for more details.) This was triggered when a RelativeLayout container was placed in
612c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * a scrolling container, such as a ScrollView or HorizontalScrollView. If a custom view
622c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * not equipped to properly measure with the MeasureSpec mode
632c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * {@link android.view.View.MeasureSpec#UNSPECIFIED UNSPECIFIED} was placed in a RelativeLayout,
642c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * this would silently work anyway as RelativeLayout would pass a very large
652c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * {@link android.view.View.MeasureSpec#AT_MOST AT_MOST} MeasureSpec instead.</p>
662c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell *
672c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * <p>This behavior has been preserved for apps that set <code>android:targetSdkVersion="17"</code>
682c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * or older in their manifest's <code>uses-sdk</code> tag for compatibility. Apps targeting SDK
692c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell * version 18 or newer will receive the correct behavior</p>
702c8cc972c3b03b76a80db517dde1e68895bbdd66Adam Powell *
714c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>See the <a href="{@docRoot}guide/topics/ui/layout/relative.html">Relative
724c359b76f9a030f92a302ba74a528faa170bad4eScott Main * Layout</a> guide.</p>
7341ec65355bd6ded652769725b276d47c54a0d913Scott Main *
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Also see {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams} for
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * layout attributes
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p>
78a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy *
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RelativeLayout_gravity
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#RelativeLayout_ignoreGravity
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project@RemoteView
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class RelativeLayout extends ViewGroup {
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TRUE = -1;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's right edge with another child's left edge.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LEFT_OF                  = 0;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's left edge with another child's right edge.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RIGHT_OF                 = 1;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's bottom edge with another child's top edge.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ABOVE                    = 2;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's top edge with another child's bottom edge.
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int BELOW                    = 3;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's baseline with another child's baseline.
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_BASELINE           = 4;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's left edge with another child's left edge.
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_LEFT               = 5;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's top edge with another child's top edge.
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_TOP                = 6;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's right edge with another child's right edge.
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_RIGHT              = 7;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns a child's bottom edge with another child's bottom edge.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_BOTTOM             = 8;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns the child's left edge with its RelativeLayout
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parent's left edge.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_PARENT_LEFT        = 9;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns the child's top edge with its RelativeLayout
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parent's top edge.
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_PARENT_TOP         = 10;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns the child's right edge with its RelativeLayout
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parent's right edge.
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_PARENT_RIGHT       = 11;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that aligns the child's bottom edge with its RelativeLayout
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parent's bottom edge.
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ALIGN_PARENT_BOTTOM      = 12;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that centers the child with respect to the bounds of its
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * RelativeLayout parent.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int CENTER_IN_PARENT         = 13;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that centers the child horizontally with respect to the
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * bounds of its RelativeLayout parent.
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int CENTER_HORIZONTAL        = 14;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rule that centers the child vertically with respect to the
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * bounds of its RelativeLayout parent.
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int CENTER_VERTICAL          = 15;
160f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    /**
161f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * Rule that aligns a child's end edge with another child's start edge.
162f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     */
163f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    public static final int START_OF                 = 16;
164f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    /**
165f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * Rule that aligns a child's start edge with another child's end edge.
166f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     */
167f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    public static final int END_OF                   = 17;
168f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    /**
169f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * Rule that aligns a child's start edge with another child's start edge.
170f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     */
171f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    public static final int ALIGN_START              = 18;
172f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    /**
173f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * Rule that aligns a child's end edge with another child's end edge.
174f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     */
175f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    public static final int ALIGN_END                = 19;
176f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    /**
177f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * Rule that aligns the child's start edge with its RelativeLayout
178f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * parent's start edge.
179f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     */
180f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    public static final int ALIGN_PARENT_START       = 20;
181f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    /**
182f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * Rule that aligns the child's end edge with its RelativeLayout
183f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * parent's end edge.
184f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     */
185f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    public static final int ALIGN_PARENT_END         = 21;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
187f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    private static final int VERB_COUNT              = 22;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
189bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy
190bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy    private static final int[] RULES_VERTICAL = {
191bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy            ABOVE, BELOW, ALIGN_BASELINE, ALIGN_TOP, ALIGN_BOTTOM
192bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy    };
193bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy
194bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy    private static final int[] RULES_HORIZONTAL = {
195f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT, START_OF, END_OF, ALIGN_START, ALIGN_END
196bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy    };
197bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View mBaselineView = null;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mHasBaselineAlignedChild;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
201f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio    private int mGravity = Gravity.START | Gravity.TOP;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Rect mContentBounds = new Rect();
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Rect mSelfBounds = new Rect();
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mIgnoreGravity;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
206725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    private SortedSet<View> mTopToBottomLeftToRightSet = null;
207725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
208725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    private boolean mDirtyHierarchy;
2096876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy    private View[] mSortedHorizontalChildren;
2106876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy    private View[] mSortedVerticalChildren;
211725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    private final DependencyGraph mGraph = new DependencyGraph();
21275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
2137da4b73a236b7c72d1337696949df7a00776dd06Adam Powell    // Compatibility hack. Old versions of the platform had problems
2147da4b73a236b7c72d1337696949df7a00776dd06Adam Powell    // with MeasureSpec value overflow and RelativeLayout was one source of them.
2157da4b73a236b7c72d1337696949df7a00776dd06Adam Powell    // Some apps came to rely on them. :(
2167da4b73a236b7c72d1337696949df7a00776dd06Adam Powell    private boolean mAllowBrokenMeasureSpecs = false;
21776d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy    // Compatibility hack. Old versions of the platform would not take
21876d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy    // margins and padding into account when generating the height measure spec
21976d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy    // for children during the horizontal measure pass.
22076d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy    private boolean mMeasureVerticalWithPaddingMargin = false;
2217da4b73a236b7c72d1337696949df7a00776dd06Adam Powell
222d5ffc79fc8c94df58509c4881b18e64cd922960eFabrice Di Meglio    // A default width used for RTL measure pass
223ca2e9e1122ba8b83d05bd144d0be31e8a3c30537Philip Milne    /**
224ca2e9e1122ba8b83d05bd144d0be31e8a3c30537Philip Milne     * Value reduced so as not to interfere with View's measurement spec. flags. See:
225ca2e9e1122ba8b83d05bd144d0be31e8a3c30537Philip Milne     * {@link View#MEASURED_SIZE_MASK}.
226ca2e9e1122ba8b83d05bd144d0be31e8a3c30537Philip Milne     * {@link View#MEASURED_STATE_TOO_SMALL}.
227ca2e9e1122ba8b83d05bd144d0be31e8a3c30537Philip Milne     **/
2283c647d23e5e00b5663f344b7c3f0ab38d74cf720Philip Milne    private static final int DEFAULT_WIDTH = 0x00010000;
229306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public RelativeLayout(Context context) {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
23276d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        queryCompatibilityModes(context);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public RelativeLayout(Context context, AttributeSet attrs) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs);
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initFromAttributes(context, attrs);
23876d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        queryCompatibilityModes(context);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public RelativeLayout(Context context, AttributeSet attrs, int defStyle) {
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs, defStyle);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initFromAttributes(context, attrs);
24476d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        queryCompatibilityModes(context);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void initFromAttributes(Context context, AttributeSet attrs) {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RelativeLayout);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIgnoreGravity = a.getResourceId(R.styleable.RelativeLayout_ignoreGravity, View.NO_ID);
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGravity = a.getInt(R.styleable.RelativeLayout_gravity, mGravity);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25476d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy    private void queryCompatibilityModes(Context context) {
25576d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        int version = context.getApplicationInfo().targetSdkVersion;
25676d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        mAllowBrokenMeasureSpecs = version <= Build.VERSION_CODES.JELLY_BEAN_MR1;
25776d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        mMeasureVerticalWithPaddingMargin = version >= Build.VERSION_CODES.JELLY_BEAN_MR2;
25876d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy    }
25976d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy
260e0a799a2ac1ca78e30fbac9e4e12a063425c08d3Patrick Dubroy    @Override
261e0a799a2ac1ca78e30fbac9e4e12a063425c08d3Patrick Dubroy    public boolean shouldDelayChildPressedState() {
262e0a799a2ac1ca78e30fbac9e4e12a063425c08d3Patrick Dubroy        return false;
263e0a799a2ac1ca78e30fbac9e4e12a063425c08d3Patrick Dubroy    }
264e0a799a2ac1ca78e30fbac9e4e12a063425c08d3Patrick Dubroy
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Defines which View is ignored when the gravity is applied. This setting has no
267f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * effect if the gravity is <code>Gravity.START | Gravity.TOP</code>.
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param viewId The id of the View to be ignored by gravity, or 0 if no View
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        should be ignored.
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setGravity(int)
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_ignoreGravity
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @android.view.RemotableViewMethod
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setIgnoreGravity(int viewId) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIgnoreGravity = viewId;
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2821018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     * Describes how the child views are positioned.
2831018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     *
2841018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     * @return the gravity.
2851018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     *
2861018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     * @see #setGravity(int)
2871018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     * @see android.view.Gravity
2881018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     *
2891018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     * @attr ref android.R.styleable#RelativeLayout_gravity
2901018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne     */
2911018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne    public int getGravity() {
2921018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne        return mGravity;
2931018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne    }
2941018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne
2951018fb42cb4958511a141787705aa429c5ec9bd3Philip Milne    /**
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Describes how the child views are positioned. Defaults to
297f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * <code>Gravity.START | Gravity.TOP</code>.
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2991fec24e0fff95afaa90bbf811e9f8db659eb9324Adam Powell     * <p>Note that since RelativeLayout considers the positioning of each child
3001fec24e0fff95afaa90bbf811e9f8db659eb9324Adam Powell     * relative to one another to be significant, setting gravity will affect
3011fec24e0fff95afaa90bbf811e9f8db659eb9324Adam Powell     * the positioning of all children as a single unit within the parent.
3021fec24e0fff95afaa90bbf811e9f8db659eb9324Adam Powell     * This happens after children have been relatively positioned.</p>
3031fec24e0fff95afaa90bbf811e9f8db659eb9324Adam Powell     *
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param gravity See {@link android.view.Gravity}
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setHorizontalGravity(int)
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setVerticalGravity(int)
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_gravity
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @android.view.RemotableViewMethod
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGravity(int gravity) {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mGravity != gravity) {
3146a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
3159e3b002d3f9141d54948a65e0330fdcd09e75a30Fabrice Di Meglio                gravity |= Gravity.START;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                gravity |= Gravity.TOP;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGravity = gravity;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayout();
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @android.view.RemotableViewMethod
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setHorizontalGravity(int horizontalGravity) {
3296a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio        final int gravity = horizontalGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
3306a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio        if ((mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) != gravity) {
3316a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio            mGravity = (mGravity & ~Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) | gravity;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayout();
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @android.view.RemotableViewMethod
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setVerticalGravity(int verticalGravity) {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGravity = (mGravity & ~Gravity.VERTICAL_GRAVITY_MASK) | gravity;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayout();
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getBaseline() {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBaselineView != null ? mBaselineView.getBaseline() : super.getBaseline();
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
351725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    public void requestLayout() {
352725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        super.requestLayout();
353725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        mDirtyHierarchy = true;
354725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    }
355725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
356725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    private void sortChildren() {
3576876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy        final int count = getChildCount();
3586876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy        if (mSortedVerticalChildren == null || mSortedVerticalChildren.length != count) {
3596876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy            mSortedVerticalChildren = new View[count];
3606876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy        }
3616876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy
3626876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy        if (mSortedHorizontalChildren == null || mSortedHorizontalChildren.length != count) {
3636876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy            mSortedHorizontalChildren = new View[count];
3646876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy        }
365725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
366725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        final DependencyGraph graph = mGraph;
367725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        graph.clear();
368725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
369725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        for (int i = 0; i < count; i++) {
3706876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy            graph.add(getChildAt(i));
371725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
372725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
373bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy        graph.getSortedViews(mSortedVerticalChildren, RULES_VERTICAL);
374bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy        graph.getSortedViews(mSortedHorizontalChildren, RULES_HORIZONTAL);
375725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    }
376725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
377725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    @Override
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
379725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        if (mDirtyHierarchy) {
380725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            mDirtyHierarchy = false;
381725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            sortChildren();
382725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
383725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int myWidth = -1;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int myHeight = -1;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int width = 0;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int height = 0;
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
390132a742b94b9716451ddef30cec20548b346f1b9Adam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
391132a742b94b9716451ddef30cec20548b346f1b9Adam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
392132a742b94b9716451ddef30cec20548b346f1b9Adam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
393132a742b94b9716451ddef30cec20548b346f1b9Adam Powell        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Record our dimensions if they are known;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (widthMode != MeasureSpec.UNSPECIFIED) {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            myWidth = widthSize;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (heightMode != MeasureSpec.UNSPECIFIED) {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            myHeight = heightSize;
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (widthMode == MeasureSpec.EXACTLY) {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            width = myWidth;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (heightMode == MeasureSpec.EXACTLY) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            height = myHeight;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHasBaselineAlignedChild = false;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View ignore = null;
4156a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio        int gravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
416f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        final boolean horizontalGravity = gravity != Gravity.START && gravity != 0;
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0;
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int left = Integer.MAX_VALUE;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int top = Integer.MAX_VALUE;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int right = Integer.MIN_VALUE;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int bottom = Integer.MIN_VALUE;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
425f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy        boolean offsetHorizontalAxis = false;
426f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy        boolean offsetVerticalAxis = false;
427f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((horizontalGravity || verticalGravity) && mIgnoreGravity != View.NO_ID) {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ignore = findViewById(mIgnoreGravity);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
432f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy        final boolean isWrapContentWidth = widthMode != MeasureSpec.EXACTLY;
433f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy        final boolean isWrapContentHeight = heightMode != MeasureSpec.EXACTLY;
434f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
435306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        // We need to know our size for doing the correct computation of children positioning in RTL
436306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        // mode but there is no practical way to get it instead of running the code below.
437d5ffc79fc8c94df58509c4881b18e64cd922960eFabrice Di Meglio        // So, instead of running the code twice, we just set the width to a "default display width"
438306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        // before the computation and then, as a last pass, we will update their real position with
439d5ffc79fc8c94df58509c4881b18e64cd922960eFabrice Di Meglio        // an offset equals to "DEFAULT_WIDTH - width".
440306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        final int layoutDirection = getLayoutDirection();
441306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        if (isLayoutRtl() && myWidth == -1) {
442d5ffc79fc8c94df58509c4881b18e64cd922960eFabrice Di Meglio            myWidth = DEFAULT_WIDTH;
443306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        }
444306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio
445e24ef6032f52cb754bfeb9ab32aae0a5cfa61f8aRomain Guy        View[] views = mSortedHorizontalChildren;
446725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        int count = views.length;
44713705eda8cc065ee98feb94af649615579cd4a58Fabrice Di Meglio
448725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        for (int i = 0; i < count; i++) {
449725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            View child = views[i];
450725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            if (child.getVisibility() != GONE) {
451725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                LayoutParams params = (LayoutParams) child.getLayoutParams();
452547261320cb4bbb3e967246bc86578263d94e84dFabrice Di Meglio                int[] rules = params.getRules(layoutDirection);
453956070383945db5f842ec05e507fd0233705738cRomain Guy
454547261320cb4bbb3e967246bc86578263d94e84dFabrice Di Meglio                applyHorizontalSizeRules(params, myWidth, rules);
455f782e60efc09f210643432f31b4c18026d7716d6Romain Guy                measureChildHorizontal(child, params, myWidth, myHeight);
456547261320cb4bbb3e967246bc86578263d94e84dFabrice Di Meglio
457f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) {
458f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    offsetHorizontalAxis = true;
459f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                }
460725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
461725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
462725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
463e24ef6032f52cb754bfeb9ab32aae0a5cfa61f8aRomain Guy        views = mSortedVerticalChildren;
464725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        count = views.length;
465f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
466725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        for (int i = 0; i < count; i++) {
467725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            View child = views[i];
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (child.getVisibility() != GONE) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LayoutParams params = (LayoutParams) child.getLayoutParams();
470956070383945db5f842ec05e507fd0233705738cRomain Guy
471956070383945db5f842ec05e507fd0233705738cRomain Guy                applyVerticalSizeRules(params, myHeight);
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                measureChild(child, params, myWidth, myHeight);
473f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                if (positionChildVertical(child, params, myHeight, isWrapContentHeight)) {
474f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    offsetVerticalAxis = true;
475f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
477f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                if (isWrapContentWidth) {
478306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                    if (isLayoutRtl()) {
479306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                        width = Math.max(width, myWidth - params.mLeft);
480306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                    } else {
481306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                        width = Math.max(width, params.mRight);
482306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                    }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
484f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
485f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                if (isWrapContentHeight) {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    height = Math.max(height, params.mBottom);
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (child != ignore || verticalGravity) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    left = Math.min(left, params.mLeft - params.leftMargin);
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    top = Math.min(top, params.mTop - params.topMargin);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (child != ignore || horizontalGravity) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    right = Math.max(right, params.mRight + params.rightMargin);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    bottom = Math.max(bottom, params.mBottom + params.bottomMargin);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mHasBaselineAlignedChild) {
502725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            for (int i = 0; i < count; i++) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View child = getChildAt(i);
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (child.getVisibility() != GONE) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    LayoutParams params = (LayoutParams) child.getLayoutParams();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    alignBaseline(child, params);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (child != ignore || verticalGravity) {
509725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        left = Math.min(left, params.mLeft - params.leftMargin);
510725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        top = Math.min(top, params.mTop - params.topMargin);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (child != ignore || horizontalGravity) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        right = Math.max(right, params.mRight + params.rightMargin);
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        bottom = Math.max(bottom, params.mBottom + params.bottomMargin);
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
521f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy        if (isWrapContentWidth) {
522a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy            // Width already has left padding in it since it was calculated by looking at
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the right of each child view
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            width += mPaddingRight;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mLayoutParams.width >= 0) {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                width = Math.max(width, mLayoutParams.width);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            width = Math.max(width, getSuggestedMinimumWidth());
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            width = resolveSize(width, widthMeasureSpec);
532f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
533f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            if (offsetHorizontalAxis) {
534d10a576791675628a014c0488c3d054371d4d63aRomain Guy                for (int i = 0; i < count; i++) {
535f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    View child = getChildAt(i);
536f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    if (child.getVisibility() != GONE) {
537f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                        LayoutParams params = (LayoutParams) child.getLayoutParams();
538f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        final int[] rules = params.getRules(layoutDirection);
539f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
540f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                            centerHorizontal(child, params, width);
54142460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                        } else if (rules[ALIGN_PARENT_RIGHT] != 0) {
54242460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                            final int childWidth = child.getMeasuredWidth();
54342460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                            params.mLeft = width - mPaddingRight - childWidth;
54442460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                            params.mRight = params.mLeft + childWidth;
545f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                        }
546f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    }
547f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                }
548f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            }
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
550f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
551f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy        if (isWrapContentHeight) {
552a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy            // Height already has top padding in it since it was calculated by looking at
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the bottom of each child view
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            height += mPaddingBottom;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mLayoutParams.height >= 0) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                height = Math.max(height, mLayoutParams.height);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            height = Math.max(height, getSuggestedMinimumHeight());
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            height = resolveSize(height, heightMeasureSpec);
562f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
563f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            if (offsetVerticalAxis) {
564f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                for (int i = 0; i < count; i++) {
565f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    View child = getChildAt(i);
566f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    if (child.getVisibility() != GONE) {
567f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                        LayoutParams params = (LayoutParams) child.getLayoutParams();
568f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        final int[] rules = params.getRules(layoutDirection);
569f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
570f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                            centerVertical(child, params, height);
57142460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                        } else if (rules[ALIGN_PARENT_BOTTOM] != 0) {
57242460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                            final int childHeight = child.getMeasuredHeight();
57342460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                            params.mTop = height - mPaddingBottom - childHeight;
57442460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy                            params.mBottom = params.mTop + childHeight;
575f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                        }
576f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    }
577f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                }
578f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (horizontalGravity || verticalGravity) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Rect selfBounds = mSelfBounds;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            selfBounds.set(mPaddingLeft, mPaddingTop, width - mPaddingRight,
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    height - mPaddingBottom);
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Rect contentBounds = mContentBounds;
5876a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio            Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds,
588c0053223bedf33581b0830fb87be32c1f26e5372Fabrice Di Meglio                    layoutDirection);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int horizontalOffset = contentBounds.left - left;
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int verticalOffset = contentBounds.top - top;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (horizontalOffset != 0 || verticalOffset != 0) {
593725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                for (int i = 0; i < count; i++) {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    View child = getChildAt(i);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (child.getVisibility() != GONE && child != ignore) {
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        LayoutParams params = (LayoutParams) child.getLayoutParams();
597d10a576791675628a014c0488c3d054371d4d63aRomain Guy                        if (horizontalGravity) {
598d10a576791675628a014c0488c3d054371d4d63aRomain Guy                            params.mLeft += horizontalOffset;
599d10a576791675628a014c0488c3d054371d4d63aRomain Guy                            params.mRight += horizontalOffset;
600d10a576791675628a014c0488c3d054371d4d63aRomain Guy                        }
601d10a576791675628a014c0488c3d054371d4d63aRomain Guy                        if (verticalGravity) {
602d10a576791675628a014c0488c3d054371d4d63aRomain Guy                            params.mTop += verticalOffset;
603d10a576791675628a014c0488c3d054371d4d63aRomain Guy                            params.mBottom += verticalOffset;
604d10a576791675628a014c0488c3d054371d4d63aRomain Guy                        }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
610306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        if (isLayoutRtl()) {
611306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio            final int offsetWidth = myWidth - width;
612306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio            for (int i = 0; i < count; i++) {
613306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                View child = getChildAt(i);
614306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                if (child.getVisibility() != GONE) {
615306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                    LayoutParams params = (LayoutParams) child.getLayoutParams();
616306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                    params.mLeft -= offsetWidth;
617306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                    params.mRight -= offsetWidth;
618306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio                }
619306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio            }
620306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio
621306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio        }
622306fe5cc0e85e8a5ef07ff64493982f99caeba3aFabrice Di Meglio
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMeasuredDimension(width, height);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void alignBaseline(View child, LayoutParams params) {
627e56ffdc7b31b0937628609cc3bbaa15879023569Fabrice Di Meglio        final int layoutDirection = getLayoutDirection();
628f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        int[] rules = params.getRules(layoutDirection);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int anchorBaseline = getRelatedViewBaseline(rules, ALIGN_BASELINE);
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorBaseline != -1) {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LayoutParams anchorParams = getRelatedViewParams(rules, ALIGN_BASELINE);
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (anchorParams != null) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int offset = anchorParams.mTop + anchorBaseline;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int baseline = child.getBaseline();
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (baseline != -1) {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    offset -= baseline;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int height = params.mBottom - params.mTop;
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                params.mTop = offset;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                params.mBottom = params.mTop + height;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBaselineView == null) {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBaselineView = child;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LayoutParams lp = (LayoutParams) mBaselineView.getLayoutParams();
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (params.mTop < lp.mTop || (params.mTop == lp.mTop && params.mLeft < lp.mLeft)) {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBaselineView = child;
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Measure a child. The child should have left, top, right and bottom information
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * stored in its LayoutParams. If any of these values is -1 it means that the view
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can extend up to the corresponding edge.
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param child Child to measure
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param params LayoutParams associated with child
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param myWidth Width of the the RelativeLayout
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param myHeight Height of the RelativeLayout
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
665725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    private void measureChild(View child, LayoutParams params, int myWidth, int myHeight) {
666e8fb03c05899c00f55ab1990e1b16038e82d1167Romain Guy        int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
667e8fb03c05899c00f55ab1990e1b16038e82d1167Romain Guy                params.mRight, params.width,
668e8fb03c05899c00f55ab1990e1b16038e82d1167Romain Guy                params.leftMargin, params.rightMargin,
669e8fb03c05899c00f55ab1990e1b16038e82d1167Romain Guy                mPaddingLeft, mPaddingRight,
670e8fb03c05899c00f55ab1990e1b16038e82d1167Romain Guy                myWidth);
6711b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy        int childHeightMeasureSpec = getChildMeasureSpec(params.mTop,
6721b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy                params.mBottom, params.height,
6731b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy                params.topMargin, params.bottomMargin,
6741b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy                mPaddingTop, mPaddingBottom,
6751b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy                myHeight);
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679f782e60efc09f210643432f31b4c18026d7716d6Romain Guy    private void measureChildHorizontal(View child, LayoutParams params, int myWidth, int myHeight) {
680956070383945db5f842ec05e507fd0233705738cRomain Guy        int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
681956070383945db5f842ec05e507fd0233705738cRomain Guy                params.mRight, params.width,
682956070383945db5f842ec05e507fd0233705738cRomain Guy                params.leftMargin, params.rightMargin,
683956070383945db5f842ec05e507fd0233705738cRomain Guy                mPaddingLeft, mPaddingRight,
684956070383945db5f842ec05e507fd0233705738cRomain Guy                myWidth);
68576d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        int maxHeight = myHeight;
68676d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        if (mMeasureVerticalWithPaddingMargin) {
68776d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy            maxHeight = Math.max(0, myHeight - mPaddingTop - mPaddingBottom -
68876d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy                    params.topMargin - params.bottomMargin);
68976d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy        }
690f782e60efc09f210643432f31b4c18026d7716d6Romain Guy        int childHeightMeasureSpec;
6917da4b73a236b7c72d1337696949df7a00776dd06Adam Powell        if (myHeight < 0 && !mAllowBrokenMeasureSpecs) {
692f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            if (params.height >= 0) {
693f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy                childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
694f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy                        params.height, MeasureSpec.EXACTLY);
695f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            } else {
696f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy                // Negative values in a mySize/myWidth/myWidth value in RelativeLayout measurement
697f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy                // is code for, "we got an unspecified mode in the RelativeLayout's measurespec."
698f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy                // Carry it forward.
699f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy                childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
700f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            }
701132a742b94b9716451ddef30cec20548b346f1b9Adam Powell        } else if (params.width == LayoutParams.MATCH_PARENT) {
70276d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY);
703f782e60efc09f210643432f31b4c18026d7716d6Romain Guy        } else {
70476d59a3b7b3ceea1d0854e588532cfc91b44201dRomain Guy            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
705f782e60efc09f210643432f31b4c18026d7716d6Romain Guy        }
706725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
707725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    }
708725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get a measure spec that accounts for all of the constraints on this view.
711f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * This includes size constraints imposed by the RelativeLayout as well as
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the View's desired dimension.
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childStart The left or top field of the child's layout params
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childEnd The right or bottom field of the child's layout params
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childSize The child's desired size (the width or height field of
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        the child's layout params)
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startMargin The left or top margin
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param endMargin The right or bottom margin
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startPadding mPaddingLeft or mPaddingTop
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param endPadding mPaddingRight or mPaddingBottom
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mySize The width or height of this view (the RelativeLayout)
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return MeasureSpec for the child
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getChildMeasureSpec(int childStart, int childEnd,
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int childSize, int startMargin, int endMargin, int startPadding,
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int endPadding, int mySize) {
7287da4b73a236b7c72d1337696949df7a00776dd06Adam Powell        if (mySize < 0 && !mAllowBrokenMeasureSpecs) {
729f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            if (childSize >= 0) {
730f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy                return MeasureSpec.makeMeasureSpec(childSize, MeasureSpec.EXACTLY);
731f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            }
732132a742b94b9716451ddef30cec20548b346f1b9Adam Powell            // Negative values in a mySize/myWidth/myWidth value in RelativeLayout measurement
733132a742b94b9716451ddef30cec20548b346f1b9Adam Powell            // is code for, "we got an unspecified mode in the RelativeLayout's measurespec."
734132a742b94b9716451ddef30cec20548b346f1b9Adam Powell            // Carry it forward.
735132a742b94b9716451ddef30cec20548b346f1b9Adam Powell            return MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
736132a742b94b9716451ddef30cec20548b346f1b9Adam Powell        }
737132a742b94b9716451ddef30cec20548b346f1b9Adam Powell
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childSpecMode = 0;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childSpecSize = 0;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Figure out start and end bounds.
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int tempStart = childStart;
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int tempEnd = childEnd;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the view did not express a layout constraint for an edge, use
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // view's margins and our padding
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tempStart < 0) {
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tempStart = startPadding + startMargin;
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tempEnd < 0) {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tempEnd = mySize - endPadding - endMargin;
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Figure out maximum size available to this view
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int maxAvailable = tempEnd - tempStart;
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (childStart >= 0 && childEnd >= 0) {
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Constraints fixed both edges, so child must be an exact size
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childSpecMode = MeasureSpec.EXACTLY;
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childSpecSize = maxAvailable;
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (childSize >= 0) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Child wanted an exact size. Give as much as possible
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childSpecMode = MeasureSpec.EXACTLY;
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (maxAvailable >= 0) {
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We have a maxmum size in this dimension.
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childSpecSize = Math.min(maxAvailable, childSize);
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We can grow in this dimension.
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childSpecSize = childSize;
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
773980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy            } else if (childSize == LayoutParams.MATCH_PARENT) {
774f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                // Child wanted to be as big as possible. Give all available
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // space
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childSpecMode = MeasureSpec.EXACTLY;
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childSpecSize = maxAvailable;
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (childSize == LayoutParams.WRAP_CONTENT) {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Child wants to wrap content. Use AT_MOST
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // to communicate available space if we know
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // our max size
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (maxAvailable >= 0) {
783f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    // We have a maximum size in this dimension.
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childSpecMode = MeasureSpec.AT_MOST;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childSpecSize = maxAvailable;
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We can grow in this dimension. Child can be as big as it
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // wants
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childSpecMode = MeasureSpec.UNSPECIFIED;
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childSpecSize = 0;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return MeasureSpec.makeMeasureSpec(childSpecSize, childSpecMode);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
798f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy    private boolean positionChildHorizontal(View child, LayoutParams params, int myWidth,
799f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            boolean wrapContent) {
800f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
801e56ffdc7b31b0937628609cc3bbaa15879023569Fabrice Di Meglio        final int layoutDirection = getLayoutDirection();
802f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        int[] rules = params.getRules(layoutDirection);
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (params.mLeft < 0 && params.mRight >= 0) {
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Right is fixed, but left varies
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            params.mLeft = params.mRight - child.getMeasuredWidth();
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (params.mLeft >= 0 && params.mRight < 0) {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Left is fixed, but right varies
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            params.mRight = params.mLeft + child.getMeasuredWidth();
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (params.mLeft < 0 && params.mRight < 0) {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Both left and right vary
812f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
813f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                if (!wrapContent) {
814f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    centerHorizontal(child, params, myWidth);
815f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                } else {
816f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    params.mLeft = mPaddingLeft + params.leftMargin;
817f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    params.mRight = params.mLeft + child.getMeasuredWidth();
818f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                }
819f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                return true;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
821f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                // This is the default case. For RTL we start from the right and for LTR we start
822f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                // from the left. This will give LEFT/TOP for LTR and RIGHT/TOP for RTL.
823f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                if (isLayoutRtl()) {
824f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    params.mRight = myWidth - mPaddingRight- params.rightMargin;
825f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    params.mLeft = params.mRight - child.getMeasuredWidth();
826f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                } else {
827f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    params.mLeft = mPaddingLeft + params.leftMargin;
828f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    params.mRight = params.mLeft + child.getMeasuredWidth();
829f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                }
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
832f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        return rules[ALIGN_PARENT_END] != 0;
833725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    }
834725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
835f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy    private boolean positionChildVertical(View child, LayoutParams params, int myHeight,
836f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            boolean wrapContent) {
837f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy
838725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        int[] rules = params.getRules();
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (params.mTop < 0 && params.mBottom >= 0) {
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Bottom is fixed, but top varies
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            params.mTop = params.mBottom - child.getMeasuredHeight();
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (params.mTop >= 0 && params.mBottom < 0) {
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Top is fixed, but bottom varies
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            params.mBottom = params.mTop + child.getMeasuredHeight();
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (params.mTop < 0 && params.mBottom < 0) {
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Both top and bottom vary
848f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy            if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
849f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                if (!wrapContent) {
850f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    centerVertical(child, params, myHeight);
851f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                } else {
852f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    params.mTop = mPaddingTop + params.topMargin;
853f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                    params.mBottom = params.mTop + child.getMeasuredHeight();
854f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                }
855f7dabb088a474f821d1b07af9a51d063b4782537Romain Guy                return true;
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                params.mTop = mPaddingTop + params.topMargin;
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                params.mBottom = params.mTop + child.getMeasuredHeight();
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
86142460ac1bb5512a17a6891f7d99e2b45db0889d8Romain Guy        return rules[ALIGN_PARENT_BOTTOM] != 0;
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
864547261320cb4bbb3e967246bc86578263d94e84dFabrice Di Meglio    private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth, int[] rules) {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RelativeLayout.LayoutParams anchorParams;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // -1 indicated a "soft requirement" in that direction. For example:
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // left=10, right=-1 means the view must start at 10, but can go as far as it wants to the right
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // left =-1, right=10 means the view must end at 10, but can go as far as it wants to the left
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // left=10, right=20 means the left and right ends are both fixed
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        childParams.mLeft = -1;
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        childParams.mRight = -1;
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, LEFT_OF);
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mRight = anchorParams.mLeft - (anchorParams.leftMargin +
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParams.rightMargin);
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[LEFT_OF] != 0) {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (myWidth >= 0) {
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, RIGHT_OF);
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mLeft = anchorParams.mRight + (anchorParams.rightMargin +
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParams.leftMargin);
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[RIGHT_OF] != 0) {
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mLeft = mPaddingLeft + childParams.leftMargin;
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, ALIGN_LEFT);
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mLeft = anchorParams.mLeft + childParams.leftMargin;
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[ALIGN_LEFT] != 0) {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mLeft = mPaddingLeft + childParams.leftMargin;
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, ALIGN_RIGHT);
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mRight = anchorParams.mRight - childParams.rightMargin;
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[ALIGN_RIGHT] != 0) {
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (myWidth >= 0) {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9081b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy        if (0 != rules[ALIGN_PARENT_LEFT]) {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mLeft = mPaddingLeft + childParams.leftMargin;
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9121b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy        if (0 != rules[ALIGN_PARENT_RIGHT]) {
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (myWidth >= 0) {
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
917725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    }
918725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
919725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    private void applyVerticalSizeRules(LayoutParams childParams, int myHeight) {
920725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        int[] rules = childParams.getRules();
921725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        RelativeLayout.LayoutParams anchorParams;
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        childParams.mTop = -1;
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        childParams.mBottom = -1;
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, ABOVE);
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mBottom = anchorParams.mTop - (anchorParams.topMargin +
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParams.bottomMargin);
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[ABOVE] != 0) {
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (myHeight >= 0) {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, BELOW);
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mTop = anchorParams.mBottom + (anchorParams.bottomMargin +
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    childParams.topMargin);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[BELOW] != 0) {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mTop = mPaddingTop + childParams.topMargin;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, ALIGN_TOP);
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mTop = anchorParams.mTop + childParams.topMargin;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[ALIGN_TOP] != 0) {
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mTop = mPaddingTop + childParams.topMargin;
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchorParams = getRelatedViewParams(rules, ALIGN_BOTTOM);
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchorParams != null) {
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mBottom = anchorParams.mBottom - childParams.bottomMargin;
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (childParams.alignWithParent && rules[ALIGN_BOTTOM] != 0) {
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (myHeight >= 0) {
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin;
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9601b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy        if (0 != rules[ALIGN_PARENT_TOP]) {
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childParams.mTop = mPaddingTop + childParams.topMargin;
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9641b7c791adf6d5e113cd07fa1a9cbef310f79145aRomain Guy        if (0 != rules[ALIGN_PARENT_BOTTOM]) {
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (myHeight >= 0) {
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin;
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (rules[ALIGN_BASELINE] != 0) {
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHasBaselineAlignedChild = true;
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View getRelatedView(int[] rules, int relation) {
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int id = rules[relation];
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id != 0) {
9781ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            DependencyGraph.Node node = mGraph.mKeyNodes.get(id);
979a0fd1d742d8edaf6c7e79bdd16a9b0c44fda4503Romain Guy            if (node == null) return null;
980a0fd1d742d8edaf6c7e79bdd16a9b0c44fda4503Romain Guy            View v = node.view;
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Find the first non-GONE view up the chain
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (v.getVisibility() == View.GONE) {
98413705eda8cc065ee98feb94af649615579cd4a58Fabrice Di Meglio                rules = ((LayoutParams) v.getLayoutParams()).getRules(v.getLayoutDirection());
9851ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy                node = mGraph.mKeyNodes.get((rules[relation]));
986a0fd1d742d8edaf6c7e79bdd16a9b0c44fda4503Romain Guy                if (node == null) return null;
987a0fd1d742d8edaf6c7e79bdd16a9b0c44fda4503Romain Guy                v = node.view;
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return v;
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LayoutParams getRelatedViewParams(int[] rules, int relation) {
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View v = getRelatedView(rules, relation);
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (v != null) {
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ViewGroup.LayoutParams params = v.getLayoutParams();
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (params instanceof LayoutParams) {
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return (LayoutParams) v.getLayoutParams();
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getRelatedViewBaseline(int[] rules, int relation) {
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View v = getRelatedView(rules, relation);
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (v != null) {
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return v.getBaseline();
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1015f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy    private static void centerHorizontal(View child, LayoutParams params, int myWidth) {
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childWidth = child.getMeasuredWidth();
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int left = (myWidth - childWidth) / 2;
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        params.mLeft = left;
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        params.mRight = left + childWidth;
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1023f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy    private static void centerVertical(View child, LayoutParams params, int myHeight) {
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childHeight = child.getMeasuredHeight();
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int top = (myHeight - childHeight) / 2;
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        params.mTop = top;
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        params.mBottom = top + childHeight;
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onLayout(boolean changed, int l, int t, int r, int b) {
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //  The layout has actually already been performed and the positions
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //  cached.  Apply the cached values to the children.
103513705eda8cc065ee98feb94af649615579cd4a58Fabrice Di Meglio        final int count = getChildCount();
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < count; i++) {
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View child = getChildAt(i);
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (child.getVisibility() != GONE) {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                RelativeLayout.LayoutParams st =
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (RelativeLayout.LayoutParams) child.getLayoutParams();
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom);
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public LayoutParams generateLayoutParams(AttributeSet attrs) {
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new RelativeLayout.LayoutParams(getContext(), attrs);
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a set of layout parameters with a width of
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT},
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and no spanning.
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Override to allow type-checking of LayoutParams.
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return p instanceof RelativeLayout.LayoutParams;
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new LayoutParams(p);
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
107375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    @Override
107475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
107575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        if (mTopToBottomLeftToRightSet == null) {
107675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            mTopToBottomLeftToRightSet = new TreeSet<View>(new TopToBottomLeftToRightComparator());
107775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
107875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
107975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        // sort children top-to-bottom and left-to-right
108075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        for (int i = 0, count = getChildCount(); i < count; i++) {
108175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            mTopToBottomLeftToRightSet.add(getChildAt(i));
108275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
108375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
108475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        for (View view : mTopToBottomLeftToRightSet) {
10850b0a41d8e26eaf0f1d9d922621494daf40964a9aSvetoslav Ganov            if (view.getVisibility() == View.VISIBLE
10860b0a41d8e26eaf0f1d9d922621494daf40964a9aSvetoslav Ganov                    && view.dispatchPopulateAccessibilityEvent(event)) {
108775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                mTopToBottomLeftToRightSet.clear();
108875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                return true;
108975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
109075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
109175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
109275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        mTopToBottomLeftToRightSet.clear();
109375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        return false;
109475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
109575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
10968a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
10978a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
10988a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityEvent(event);
10998a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        event.setClassName(RelativeLayout.class.getName());
11008a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
11018a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
11028a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
11038a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
11048a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityNodeInfo(info);
11058a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        info.setClassName(RelativeLayout.class.getName());
11068a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
11078a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
110875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
110975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Compares two views in left-to-right and top-to-bottom fashion.
111075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
111175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     private class TopToBottomLeftToRightComparator implements Comparator<View> {
111275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        public int compare(View first, View second) {
111375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            // top - bottom
111475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            int topDifference = first.getTop() - second.getTop();
111575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            if (topDifference != 0) {
111675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                return topDifference;
111775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
111875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            // left - right
111975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            int leftDifference = first.getLeft() - second.getLeft();
112075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            if (leftDifference != 0) {
112175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                return leftDifference;
112275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
112375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            // break tie by height
112475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            int heightDiference = first.getHeight() - second.getHeight();
112575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            if (heightDiference != 0) {
112675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                return heightDiference;
112775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
112875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            // break tie by width
112975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            int widthDiference = first.getWidth() - second.getWidth();
113075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            if (widthDiference != 0) {
113175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                return widthDiference;
113275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
113375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            return 0;
113475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
113575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
113675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Per-child layout information associated with RelativeLayout.
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignWithParentIfMissing
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toLeftOf
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toRightOf
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_above
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_below
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignBaseline
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignLeft
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignTop
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignRight
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignBottom
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentLeft
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentTop
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentRight
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentBottom
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerInParent
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerHorizontal
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerVertical
1157f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toStartOf
1158f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toEndOf
1159f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignStart
1160f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignEnd
1161f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentStart
1162f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio     * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentEnd
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
1165bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev        @ViewDebug.ExportedProperty(category = "layout", resolveId = true, indexMapping = {
1166c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ABOVE,               to = "above"),
1167c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_BASELINE,      to = "alignBaseline"),
1168c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_BOTTOM,        to = "alignBottom"),
1169c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_LEFT,          to = "alignLeft"),
1170c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_PARENT_BOTTOM, to = "alignParentBottom"),
1171c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_PARENT_LEFT,   to = "alignParentLeft"),
1172c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_PARENT_RIGHT,  to = "alignParentRight"),
1173c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_PARENT_TOP,    to = "alignParentTop"),
1174c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_RIGHT,         to = "alignRight"),
1175c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = ALIGN_TOP,           to = "alignTop"),
1176c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = BELOW,               to = "below"),
1177c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = CENTER_HORIZONTAL,   to = "centerHorizontal"),
1178c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = CENTER_IN_PARENT,    to = "center"),
1179c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = CENTER_VERTICAL,     to = "centerVertical"),
1180c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project            @ViewDebug.IntToString(from = LEFT_OF,             to = "leftOf"),
1181f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            @ViewDebug.IntToString(from = RIGHT_OF,            to = "rightOf"),
1182f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            @ViewDebug.IntToString(from = ALIGN_START,         to = "alignStart"),
1183f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            @ViewDebug.IntToString(from = ALIGN_END,           to = "alignEnd"),
1184f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            @ViewDebug.IntToString(from = ALIGN_PARENT_START,  to = "alignParentStart"),
1185f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            @ViewDebug.IntToString(from = ALIGN_PARENT_END,    to = "alignParentEnd"),
1186f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            @ViewDebug.IntToString(from = START_OF,            to = "startOf"),
1187f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            @ViewDebug.IntToString(from = END_OF,              to = "endOf")
1188105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }, mapping = {
1189105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            @ViewDebug.IntToString(from = TRUE, to = "true"),
1190a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy            @ViewDebug.IntToString(from = 0,    to = "false/NO_ID")
1191105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        })
1192f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int[] mRules = new int[VERB_COUNT];
1194f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        private int[] mInitialRules = new int[VERB_COUNT];
1195c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mLeft, mTop, mRight, mBottom;
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11980072f64939b37a4d84940656c2180ad2e0594ff4Fabrice Di Meglio        private int mStart = DEFAULT_MARGIN_RELATIVE;
11990072f64939b37a4d84940656c2180ad2e0594ff4Fabrice Di Meglio        private int mEnd = DEFAULT_MARGIN_RELATIVE;
1200f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
1201f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        private boolean mRulesChanged = false;
1202c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        private boolean mIsRtlCompatibilityMode = false;
1203f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * When true, uses the parent as the anchor if the anchor doesn't exist or if
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the anchor's visibility is GONE.
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1208bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev        @ViewDebug.ExportedProperty(category = "layout")
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean alignWithParent;
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LayoutParams(Context c, AttributeSet attrs) {
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(c, attrs);
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            TypedArray a = c.obtainStyledAttributes(attrs,
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.styleable.RelativeLayout_Layout);
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1217c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio            final int targetSdkVersion = c.getApplicationInfo().targetSdkVersion;
1218c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio            mIsRtlCompatibilityMode = (targetSdkVersion < JELLY_BEAN_MR1 ||
1219c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    !c.getApplicationInfo().hasRtlSupport());
1220c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int[] rules = mRules;
1222f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            //noinspection MismatchedReadAndWriteOfArray
1223f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            final int[] initialRules = mInitialRules;
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = a.getIndexCount();
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < N; i++) {
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int attr = a.getIndex(i);
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (attr) {
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignWithParentIfMissing:
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        alignWithParent = a.getBoolean(attr, false);
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toLeftOf:
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[LEFT_OF] = a.getResourceId(attr, 0);
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toRightOf:
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[RIGHT_OF] = a.getResourceId(attr, 0);
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_above:
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ABOVE] = a.getResourceId(attr, 0);
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_below:
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[BELOW] = a.getResourceId(attr, 0);
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBaseline:
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_BASELINE] = a.getResourceId(attr, 0);
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignLeft:
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_LEFT] = a.getResourceId(attr, 0);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignTop:
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_TOP] = a.getResourceId(attr, 0);
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignRight:
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_RIGHT] = a.getResourceId(attr, 0);
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBottom:
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_BOTTOM] = a.getResourceId(attr, 0);
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentLeft:
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_PARENT_LEFT] = a.getBoolean(attr, false) ? TRUE : 0;
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentTop:
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_PARENT_TOP] = a.getBoolean(attr, false) ? TRUE : 0;
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentRight:
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_PARENT_RIGHT] = a.getBoolean(attr, false) ? TRUE : 0;
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentBottom:
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[ALIGN_PARENT_BOTTOM] = a.getBoolean(attr, false) ? TRUE : 0;
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerInParent:
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[CENTER_IN_PARENT] = a.getBoolean(attr, false) ? TRUE : 0;
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerHorizontal:
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[CENTER_HORIZONTAL] = a.getBoolean(attr, false) ? TRUE : 0;
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerVertical:
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        rules[CENTER_VERTICAL] = a.getBoolean(attr, false) ? TRUE : 0;
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       break;
1280f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toStartOf:
1281f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        rules[START_OF] = a.getResourceId(attr, 0);
1282f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        break;
1283f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toEndOf:
1284f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        rules[END_OF] = a.getResourceId(attr, 0);
1285f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        break;
1286f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignStart:
1287f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        rules[ALIGN_START] = a.getResourceId(attr, 0);
1288f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        break;
1289f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignEnd:
1290f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        rules[ALIGN_END] = a.getResourceId(attr, 0);
1291f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        break;
1292f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentStart:
1293f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        rules[ALIGN_PARENT_START] = a.getBoolean(attr, false) ? TRUE : 0;
1294f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        break;
1295f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentEnd:
1296f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        rules[ALIGN_PARENT_END] = a.getBoolean(attr, false) ? TRUE : 0;
1297f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                        break;
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13000072f64939b37a4d84940656c2180ad2e0594ff4Fabrice Di Meglio            mRulesChanged = true;
1301f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            System.arraycopy(rules, LEFT_OF, initialRules, LEFT_OF, VERB_COUNT);
1302f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            a.recycle();
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LayoutParams(int w, int h) {
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(w, h);
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@inheritDoc}
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LayoutParams(ViewGroup.LayoutParams source) {
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(source);
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@inheritDoc}
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public LayoutParams(ViewGroup.MarginLayoutParams source) {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(source);
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String debug(String output) {
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return output + "ViewGroup.LayoutParams={ width=" + sizeToString(width) +
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", height=" + sizeToString(height) + " }";
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Adds a layout rule to be interpreted by the RelativeLayout. This
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * method should only be used for constraints that don't refer to another sibling
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * (e.g., CENTER_IN_PARENT) or take a boolean value ({@link RelativeLayout#TRUE}
1334f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * for true or 0 for false). To specify a verb that takes a subject, use
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link #addRule(int, int)} instead.
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param verb One of the verbs defined by
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *        {@link android.widget.RelativeLayout RelativeLayout}, such as
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *        ALIGN_WITH_PARENT_LEFT.
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see #addRule(int, int)
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void addRule(int verb) {
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRules[verb] = TRUE;
1344f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            mInitialRules[verb] = TRUE;
1345f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            mRulesChanged = true;
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Adds a layout rule to be interpreted by the RelativeLayout. Use this for
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * verbs that take a target, such as a sibling (ALIGN_RIGHT) or a boolean
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * value (VISIBLE).
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param verb One of the verbs defined by
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *        {@link android.widget.RelativeLayout RelativeLayout}, such as
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *         ALIGN_WITH_PARENT_LEFT.
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param anchor The id of another view to use as an anchor,
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *        or a boolean value(represented as {@link RelativeLayout#TRUE})
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *        for true or 0 for false).  For verbs that don't refer to another sibling
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *        (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1.
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see #addRule(int)
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void addRule(int verb, int anchor) {
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRules[verb] = anchor;
1364f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            mInitialRules[verb] = anchor;
1365f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            mRulesChanged = true;
1366f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        }
1367f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
1368a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio        /**
1369a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         * Removes a layout rule to be interpreted by the RelativeLayout.
1370a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         *
1371a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         * @param verb One of the verbs defined by
1372a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         *        {@link android.widget.RelativeLayout RelativeLayout}, such as
1373a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         *         ALIGN_WITH_PARENT_LEFT.
1374a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         * @see #addRule(int)
1375a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         * @see #addRule(int, int)
1376a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio         */
1377a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio        public void removeRule(int verb) {
1378a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio            mRules[verb] = 0;
1379a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio            mInitialRules[verb] = 0;
1380a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio            mRulesChanged = true;
1381a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio        }
1382a4c1030870d8c91b6d871922c3e6962323700f25Fabrice Di Meglio
1383f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        private boolean hasRelativeRules() {
1384f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            return (mInitialRules[START_OF] != 0 || mInitialRules[END_OF] != 0 ||
1385f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    mInitialRules[ALIGN_START] != 0 || mInitialRules[ALIGN_END] != 0 ||
1386f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    mInitialRules[ALIGN_PARENT_START] != 0 || mInitialRules[ALIGN_PARENT_END] != 0);
1387f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        }
1388f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
1389c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // The way we are resolving rules depends on the layout direction and if we are pre JB MR1
1390c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // or not.
1391c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        //
1392c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // If we are pre JB MR1 (said as "RTL compatibility mode"), "left"/"right" rules are having
1393c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // predominance over any "start/end" rules that could have been defined. A special case:
1394c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // if no "left"/"right" rule has been defined and "start"/"end" rules are defined then we
1395c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // resolve those "start"/"end" rules to "left"/"right" respectively.
1396c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        //
1397c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // If we are JB MR1+, then "start"/"end" rules are having predominance over "left"/"right"
1398c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // rules. If no "start"/"end" rule is defined then we use "left"/"right" rules.
1399c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        //
1400c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // In all cases, the result of the resolution should clear the "start"/"end" rules to leave
1401c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio        // only the "left"/"right" rules at the end.
1402f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        private void resolveRules(int layoutDirection) {
1403f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            final boolean isLayoutRtl = (layoutDirection == View.LAYOUT_DIRECTION_RTL);
1404c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1405f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            // Reset to initial state
1406f16c7a97548cedccea291ffebc4388a7f15c9aa1Romain Guy            System.arraycopy(mInitialRules, LEFT_OF, mRules, LEFT_OF, VERB_COUNT);
1407c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1408c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio            // Apply rules depending on direction and if we are in RTL compatibility mode
1409c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio            if (mIsRtlCompatibilityMode) {
1410c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_START] != 0) {
1411c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    if (mRules[ALIGN_LEFT] == 0) {
1412c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "left" rule is not defined but "start" rule is: use the "start" rule as
1413c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // the "left" rule
1414c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        mRules[ALIGN_LEFT] = mRules[ALIGN_START];
1415c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    }
1416c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_START] = 0;
1417c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1418c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1419c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_END] != 0) {
1420c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    if (mRules[ALIGN_RIGHT] == 0) {
1421c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "right" rule is not defined but "end" rule is: use the "end" rule as the
1422c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "right" rule
1423c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        mRules[ALIGN_RIGHT] = mRules[ALIGN_END];
1424c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    }
1425c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_END] = 0;
1426c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1427c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1428c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[START_OF] != 0) {
1429c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    if (mRules[LEFT_OF] == 0) {
1430c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "left" rule is not defined but "start" rule is: use the "start" rule as
1431c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // the "left" rule
1432c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        mRules[LEFT_OF] = mRules[START_OF];
1433c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    }
1434c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[START_OF] = 0;
1435c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1436c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1437c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[END_OF] != 0) {
1438c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    if (mRules[RIGHT_OF] == 0) {
1439c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "right" rule is not defined but "end" rule is: use the "end" rule as the
1440c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "right" rule
1441c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        mRules[RIGHT_OF] = mRules[END_OF];
1442c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    }
1443c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[END_OF] = 0;
1444c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1445c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1446c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_PARENT_START] != 0) {
1447c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    if (mRules[ALIGN_PARENT_LEFT] == 0) {
1448c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "left" rule is not defined but "start" rule is: use the "start" rule as
1449c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // the "left" rule
1450c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        mRules[ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START];
1451c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    }
1452c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_PARENT_START] = 0;
1453c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1454c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1455c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_PARENT_RIGHT] == 0) {
1456c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    if (mRules[ALIGN_PARENT_RIGHT] == 0) {
1457c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "right" rule is not defined but "end" rule is: use the "end" rule as the
1458c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        // "right" rule
1459c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        mRules[ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END];
1460c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    }
1461c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_PARENT_END] = 0;
1462c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1463c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio            } else {
1464c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                // JB MR1+ case
1465c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if ((mRules[ALIGN_START] != 0 || mRules[ALIGN_END] != 0) &&
1466c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        (mRules[ALIGN_LEFT] != 0 || mRules[ALIGN_RIGHT] != 0)) {
1467c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "start"/"end" rules take precedence over "left"/"right" rules
1468c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_LEFT] = 0;
1469c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_RIGHT] = 0;
1470c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1471c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_START] != 0) {
1472c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "start" rule resolved to "left" or "right" depending on the direction
1473c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[isLayoutRtl ? ALIGN_RIGHT : ALIGN_LEFT] = mRules[ALIGN_START];
1474c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_START] = 0;
1475c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1476c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_END] != 0) {
1477c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "end" rule resolved to "left" or "right" depending on the direction
1478c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[isLayoutRtl ? ALIGN_LEFT : ALIGN_RIGHT] = mRules[ALIGN_END];
1479c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_END] = 0;
1480c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1481c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1482c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if ((mRules[START_OF] != 0 || mRules[END_OF] != 0) &&
1483c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        (mRules[LEFT_OF] != 0 || mRules[RIGHT_OF] != 0)) {
1484c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "start"/"end" rules take precedence over "left"/"right" rules
1485c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[LEFT_OF] = 0;
1486c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[RIGHT_OF] = 0;
1487c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1488c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[START_OF] != 0) {
1489c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "start" rule resolved to "left" or "right" depending on the direction
1490c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[isLayoutRtl ? RIGHT_OF : LEFT_OF] = mRules[START_OF];
1491c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[START_OF] = 0;
1492c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1493c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[END_OF] != 0) {
1494c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "end" rule resolved to "left" or "right" depending on the direction
1495c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[isLayoutRtl ? LEFT_OF : RIGHT_OF] = mRules[END_OF];
1496c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[END_OF] = 0;
1497c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1498c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio
1499c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if ((mRules[ALIGN_PARENT_START] != 0 || mRules[ALIGN_PARENT_END] != 0) &&
1500c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                        (mRules[ALIGN_PARENT_LEFT] != 0 || mRules[ALIGN_PARENT_RIGHT] != 0)) {
1501c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "start"/"end" rules take precedence over "left"/"right" rules
1502c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_PARENT_LEFT] = 0;
1503c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_PARENT_RIGHT] = 0;
1504c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1505c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_PARENT_START] != 0) {
1506c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "start" rule resolved to "left" or "right" depending on the direction
1507c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[isLayoutRtl ? ALIGN_PARENT_RIGHT : ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START];
1508c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_PARENT_START] = 0;
1509c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1510c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                if (mRules[ALIGN_PARENT_END] != 0) {
1511c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    // "end" rule resolved to "left" or "right" depending on the direction
1512c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[isLayoutRtl ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END];
1513c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                    mRules[ALIGN_PARENT_END] = 0;
1514c44d880c508ded633b61930e1964df70876ec42fFabrice Di Meglio                }
1515f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            }
1516f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            mRulesChanged = false;
1517f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        }
1518f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
1519f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        /**
1520f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * Retrieves a complete list of all supported rules, where the index is the rule
1521f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * verb, and the element value is the value specified, or "false" if it was never
1522f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * set. If there are relative rules defined (*_START / *_END), they will be resolved
1523f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * depending on the layout direction.
1524f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         *
1525f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * @param layoutDirection the direction of the layout.
1526f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         *                        Should be either {@link View#LAYOUT_DIRECTION_LTR}
1527f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         *                        or {@link View#LAYOUT_DIRECTION_RTL}
1528f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * @return the supported rules
1529f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * @see #addRule(int, int)
1530f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         *
1531f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * @hide
1532f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         */
1533f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        public int[] getRules(int layoutDirection) {
1534f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            if (hasRelativeRules() &&
1535f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    (mRulesChanged || layoutDirection != getLayoutDirection())) {
1536f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                resolveRules(layoutDirection);
1537f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                if (layoutDirection != getLayoutDirection()) {
1538f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                    setLayoutDirection(layoutDirection);
1539f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                }
1540f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            }
1541f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            return mRules;
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Retrieves a complete list of all supported rules, where the index is the rule
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * verb, and the element value is the value specified, or "false" if it was never
1547f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio         * set. There will be no resolution of relative rules done.
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return the supported rules
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see #addRule(int, int)
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int[] getRules() {
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mRules;
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1555f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
1556f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        @Override
15572918ab6c3258639148b8a5c78a34483af195246eFabrice Di Meglio        public void resolveLayoutDirection(int layoutDirection) {
1558f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            final boolean isLayoutRtl = isLayoutRtl();
1559f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            if (isLayoutRtl) {
15600072f64939b37a4d84940656c2180ad2e0594ff4Fabrice Di Meglio                if (mStart != DEFAULT_MARGIN_RELATIVE) mRight = mStart;
15610072f64939b37a4d84940656c2180ad2e0594ff4Fabrice Di Meglio                if (mEnd != DEFAULT_MARGIN_RELATIVE) mLeft = mEnd;
1562f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            } else {
15630072f64939b37a4d84940656c2180ad2e0594ff4Fabrice Di Meglio                if (mStart != DEFAULT_MARGIN_RELATIVE) mLeft = mStart;
15640072f64939b37a4d84940656c2180ad2e0594ff4Fabrice Di Meglio                if (mEnd != DEFAULT_MARGIN_RELATIVE) mRight = mEnd;
1565f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            }
1566f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio
1567f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            if (hasRelativeRules() && layoutDirection != getLayoutDirection()) {
1568f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio                resolveRules(layoutDirection);
1569f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            }
1570f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio            // This will set the layout direction
15712918ab6c3258639148b8a5c78a34483af195246eFabrice Di Meglio            super.resolveLayoutDirection(layoutDirection);
1572f443f98e7f41badd8f5d6f7bf7d26432e79a88edFabrice Di Meglio        }
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1574725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1575725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    private static class DependencyGraph {
1576725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        /**
15771ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy         * List of all views in the graph.
15781ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy         */
15791ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy        private ArrayList<Node> mNodes = new ArrayList<Node>();
15801ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy
15811ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy        /**
1582725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * List of nodes in the graph. Each node is identified by its
1583725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * view id (see View#getId()).
1584725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         */
15851ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy        private SparseArray<Node> mKeyNodes = new SparseArray<Node>();
1586725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1587725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        /**
1588725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * Temporary data structure used to build the list of roots
1589725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * for this graph.
1590725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         */
1591bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy        private ArrayDeque<Node> mRoots = new ArrayDeque<Node>();
1592725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1593725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        /**
1594725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * Clears the graph.
1595725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         */
1596725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        void clear() {
15971ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            final ArrayList<Node> nodes = mNodes;
1598725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            final int count = nodes.size();
1599725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1600725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            for (int i = 0; i < count; i++) {
16011ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy                nodes.get(i).release();
1602725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1603725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            nodes.clear();
1604725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
16051ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            mKeyNodes.clear();
1606725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            mRoots.clear();
1607725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
1608725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1609725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        /**
1610725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * Adds a view to the graph.
1611725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         *
1612725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * @param view The view to be added as a node to the graph.
1613725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         */
1614725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        void add(View view) {
16151ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            final int id = view.getId();
16161ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            final Node node = Node.acquire(view);
16171ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy
16181ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            if (id != View.NO_ID) {
16191ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy                mKeyNodes.put(id, node);
16201ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            }
16211ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy
16221ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            mNodes.add(node);
1623725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
1624725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1625725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        /**
1626725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * Builds a sorted list of views. The sorting order depends on the dependencies
1627725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * between the view. For instance, if view C needs view A to be processed first
1628725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * and view A needs view B to be processed first, the dependency graph
1629725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * is: B -> A -> C. The sorted array will contain views B, A and C in this order.
1630725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         *
1631725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * @param sorted The sorted list of views. The length of this array must
1632725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         *        be equal to getChildCount().
1633725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * @param rules The list of rules to take into account.
1634725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         */
1635725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        void getSortedViews(View[] sorted, int... rules) {
1636bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy            final ArrayDeque<Node> roots = findRoots(rules);
1637725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            int index = 0;
1638725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1639bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy            Node node;
1640bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy            while ((node = roots.pollLast()) != null) {
1641725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                final View view = node.view;
1642725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                final int key = view.getId();
1643725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1644725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                sorted[index++] = view;
1645725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
16466876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy                final ArrayMap<Node, DependencyGraph> dependents = node.dependents;
16476876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy                final int count = dependents.size();
16486876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy                for (int i = 0; i < count; i++) {
16496876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy                    final Node dependent = dependents.keyAt(i);
1650725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                    final SparseArray<Node> dependencies = dependent.dependencies;
1651725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1652725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                    dependencies.remove(key);
1653725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                    if (dependencies.size() == 0) {
1654725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        roots.add(dependent);
1655725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                    }
1656725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                }
1657725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1658725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1659725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            if (index < sorted.length) {
1660725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                throw new IllegalStateException("Circular dependencies cannot exist"
1661725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        + " in RelativeLayout");
1662725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1663725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
1664725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1665725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        /**
1666725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * Finds the roots of the graph. A root is a node with no dependency and
1667725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * with [0..n] dependents.
1668725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         *
1669725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * @param rulesFilter The list of rules to consider when building the
1670725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         *        dependencies
1671725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         *
1672725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * @return A list of node, each being a root of the graph
1673725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         */
1674bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy        private ArrayDeque<Node> findRoots(int[] rulesFilter) {
16751ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            final SparseArray<Node> keyNodes = mKeyNodes;
16761ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy            final ArrayList<Node> nodes = mNodes;
1677725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            final int count = nodes.size();
1678725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1679725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            // Find roots can be invoked several times, so make sure to clear
1680725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            // all dependents and dependencies before running the algorithm
1681725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            for (int i = 0; i < count; i++) {
16821ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy                final Node node = nodes.get(i);
1683725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                node.dependents.clear();
1684725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                node.dependencies.clear();
1685725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1686725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1687725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            // Builds up the dependents and dependencies for each node of the graph
1688725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            for (int i = 0; i < count; i++) {
16891ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy                final Node node = nodes.get(i);
1690725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1691725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                final LayoutParams layoutParams = (LayoutParams) node.view.getLayoutParams();
1692725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                final int[] rules = layoutParams.mRules;
1693725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                final int rulesCount = rulesFilter.length;
1694725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1695725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                // Look only the the rules passed in parameter, this way we build only the
1696725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                // dependencies for a specific set of rules
1697725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                for (int j = 0; j < rulesCount; j++) {
1698725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                    final int rule = rules[rulesFilter[j]];
1699725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                    if (rule > 0) {
1700725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        // The node this node depends on
17011ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy                        final Node dependency = keyNodes.get(rule);
1702da3003e1d71d66a1c936489025f8db314a2a4588Romain Guy                        // Skip unknowns and self dependencies
1703da3003e1d71d66a1c936489025f8db314a2a4588Romain Guy                        if (dependency == null || dependency == node) {
1704b8f8de85160b0a072158b45320e9fc2adba545f5Romain Guy                            continue;
1705b8f8de85160b0a072158b45320e9fc2adba545f5Romain Guy                        }
1706725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        // Add the current node as a dependent
1707bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy                        dependency.dependents.put(node, this);
1708725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        // Add a dependency to the current node
1709725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                        node.dependencies.put(rule, dependency);
1710725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                    }
1711725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                }
1712725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1713725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1714bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy            final ArrayDeque<Node> roots = mRoots;
1715725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            roots.clear();
1716725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1717725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            // Finds all the roots in the graph: all nodes with no dependencies
1718725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            for (int i = 0; i < count; i++) {
17191ab621e316828fa65e8941954e2a3c7f1d68f77aRomain Guy                final Node node = nodes.get(i);
1720bc5d876df0856e027f1e2cfce91cbdedb6aaf66fRomain Guy                if (node.dependencies.size() == 0) roots.addLast(node);
1721725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1722725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1723725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            return roots;
1724725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
1725725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1726725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        /**
1727725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * A node in the dependency graph. A node is a view, its list of dependencies
1728725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * and its list of dependents.
1729725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         *
1730725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         * A node with no dependent is considered a root of the graph.
1731725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy         */
1732abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov        static class Node {
1733725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            /**
1734725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             * The view representing this node in the layout.
1735725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             */
1736725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            View view;
1737725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1738725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            /**
1739725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             * The list of dependents for this node; a dependent is a node
1740725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             * that needs this node to be processed first.
1741725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             */
17426876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy            final ArrayMap<Node, DependencyGraph> dependents =
17436876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy                    new ArrayMap<Node, DependencyGraph>();
1744725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1745725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            /**
1746725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             * The list of dependencies for this node.
1747725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             */
1748725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            final SparseArray<Node> dependencies = new SparseArray<Node>();
1749725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1750725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            /*
1751725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             * START POOL IMPLEMENTATION
1752725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             */
1753baac46339da03aed166e8a4240ad063caad019adRomain Guy            // The pool is static, so all nodes instances are shared across
1754baac46339da03aed166e8a4240ad063caad019adRomain Guy            // activities, that's why we give it a rather high limit
1755baac46339da03aed166e8a4240ad063caad019adRomain Guy            private static final int POOL_LIMIT = 100;
17566876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy            private static final SynchronizedPool<Node> sPool =
17576876b4fb9082fe525d6edb59a834bb0e7c35ca39Romain Guy                    new SynchronizedPool<Node>(POOL_LIMIT);
17588643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
1759725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            static Node acquire(View view) {
1760abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov                Node node = sPool.acquire();
1761abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov                if (node == null) {
1762abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov                    node = new Node();
1763abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov                }
1764725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                node.view = view;
1765725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                return node;
1766725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1767725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1768725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            void release() {
1769725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                view = null;
1770725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                dependents.clear();
1771725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                dependencies.clear();
1772725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy
1773725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy                sPool.release(this);
1774725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            }
1775725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy            /*
1776725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             * END POOL IMPLEMENTATION
1777725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy             */
1778725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy        }
1779725015a9cda8f5bfcf05dff7d2b0ebbd799bb577Romain Guy    }
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1781