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