@@ -125,7 +125,25 @@ public final class Configuration implements Parcelable, Comparable<Configuration
125125 * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
126126 * resource qualifier. */
127127 public static final int SCREENLAYOUT_LONG_YES = 0x20 ;
128-
128+
129+ /** Constant for {@link #screenLayout}: bits that encode the layout direction. */
130+ public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0 ;
131+ /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */
132+ public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6 ;
133+ /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
134+ * value indicating that no layout dir has been set. */
135+ public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00 ;
136+ /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
137+ * value indicating that a layout dir has been set to LTR. */
138+ public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT ;
139+ /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK}
140+ * value indicating that a layout dir has been set to RTL. */
141+ public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT ;
142+
143+ /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
144+ public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
145+ SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED ;
146+
129147 /**
130148 * Special flag we generate to indicate that the screen layout requires
131149 * us to use a compatibility mode for apps that are not modern layout
@@ -146,6 +164,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
146164 * is wider/taller than normal. They may be one of
147165 * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.
148166 *
167+ * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
168+ * is either LTR or RTL. They may be one of
169+ * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.
170+ *
149171 * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
150172 * Multiple Screens</a> for more information.
151173 */
@@ -441,11 +463,6 @@ public boolean isLayoutSizeAtLeast(int size) {
441463 /** @hide Hack to get this information from WM to app running in compat mode. */
442464 public int compatSmallestScreenWidthDp ;
443465
444- /**
445- * @hide The layout direction associated to the current Locale
446- */
447- public int layoutDirection ;
448-
449466 /**
450467 * @hide Internal book-keeping.
451468 */
@@ -472,7 +489,6 @@ public void setTo(Configuration o) {
472489 mnc = o .mnc ;
473490 if (o .locale != null ) {
474491 locale = (Locale ) o .locale .clone ();
475- layoutDirection = o .layoutDirection ;
476492 }
477493 userSetLocale = o .userSetLocale ;
478494 touchscreen = o .touchscreen ;
@@ -517,10 +533,13 @@ public String toString() {
517533 } else {
518534 sb .append (" ?locale" );
519535 }
520- switch (layoutDirection ) {
521- case View .LAYOUT_DIRECTION_LTR : /* ltr not interesting */ break ;
522- case View .LAYOUT_DIRECTION_RTL : sb .append (" rtl" ); break ;
523- default : sb .append (" layoutDir=" ); sb .append (layoutDirection ); break ;
536+ int layoutDir = (screenLayout &SCREENLAYOUT_LAYOUTDIR_MASK );
537+ switch (layoutDir ) {
538+ case SCREENLAYOUT_LAYOUTDIR_UNDEFINED : sb .append (" ?layoutDir" ); break ;
539+ case SCREENLAYOUT_LAYOUTDIR_LTR : sb .append (" ltr" ); break ;
540+ case SCREENLAYOUT_LAYOUTDIR_RTL : sb .append (" rtl" ); break ;
541+ default : sb .append (" layoutDir=" );
542+ sb .append (layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT ); break ;
524543 }
525544 if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED ) {
526545 sb .append (" sw" ); sb .append (smallestScreenWidthDp ); sb .append ("dp" );
@@ -643,13 +662,12 @@ public void setToDefaults() {
643662 navigation = NAVIGATION_UNDEFINED ;
644663 navigationHidden = NAVIGATIONHIDDEN_UNDEFINED ;
645664 orientation = ORIENTATION_UNDEFINED ;
646- screenLayout = SCREENLAYOUT_SIZE_UNDEFINED ;
665+ screenLayout = SCREENLAYOUT_UNDEFINED ;
647666 uiMode = UI_MODE_TYPE_UNDEFINED ;
648667 screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED ;
649668 screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED ;
650669 smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED ;
651670 densityDpi = DENSITY_DPI_UNDEFINED ;
652- layoutDirection = View .LAYOUT_DIRECTION_LTR ;
653671 seq = 0 ;
654672 }
655673
@@ -685,7 +703,11 @@ public int updateFrom(Configuration delta) {
685703 changed |= ActivityInfo .CONFIG_LOCALE ;
686704 locale = delta .locale != null
687705 ? (Locale ) delta .locale .clone () : null ;
688- layoutDirection = LocaleUtil .getLayoutDirectionFromLocale (locale );
706+ // If locale has changed, then layout direction is also changed ...
707+ changed |= ActivityInfo .CONFIG_LAYOUT_DIRECTION ;
708+ // ... and we need to update the layout direction (represented by the first
709+ // 2 most significant bits in screenLayout).
710+ setLayoutDirection (locale );
689711 }
690712 if (delta .userSetLocale && (!userSetLocale || ((changed & ActivityInfo .CONFIG_LOCALE ) != 0 )))
691713 {
@@ -727,10 +749,17 @@ public int updateFrom(Configuration delta) {
727749 changed |= ActivityInfo .CONFIG_ORIENTATION ;
728750 orientation = delta .orientation ;
729751 }
730- if (delta .screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
731- && screenLayout != delta .screenLayout ) {
752+ if (getScreenLayoutNoDirection (delta .screenLayout ) !=
753+ (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED )
754+ && (getScreenLayoutNoDirection (screenLayout ) !=
755+ getScreenLayoutNoDirection (delta .screenLayout ))) {
732756 changed |= ActivityInfo .CONFIG_SCREEN_LAYOUT ;
733- screenLayout = delta .screenLayout ;
757+ // We need to preserve the previous layout dir bits if they were defined
758+ if ((delta .screenLayout &SCREENLAYOUT_LAYOUTDIR_MASK ) == 0 ) {
759+ screenLayout = (screenLayout &SCREENLAYOUT_LAYOUTDIR_MASK )|delta .screenLayout ;
760+ } else {
761+ screenLayout = delta .screenLayout ;
762+ }
734763 }
735764 if (delta .uiMode != (UI_MODE_TYPE_UNDEFINED |UI_MODE_NIGHT_UNDEFINED )
736765 && uiMode != delta .uiMode ) {
@@ -771,7 +800,6 @@ public int updateFrom(Configuration delta) {
771800 if (delta .compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED ) {
772801 compatSmallestScreenWidthDp = delta .compatSmallestScreenWidthDp ;
773802 }
774-
775803 if (delta .seq != 0 ) {
776804 seq = delta .seq ;
777805 }
@@ -807,6 +835,8 @@ public int updateFrom(Configuration delta) {
807835 * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
808836 * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
809837 * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
838+ * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
839+ * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
810840 */
811841 public int diff (Configuration delta ) {
812842 int changed = 0 ;
@@ -822,6 +852,7 @@ public int diff(Configuration delta) {
822852 if (delta .locale != null
823853 && (locale == null || !locale .equals (delta .locale ))) {
824854 changed |= ActivityInfo .CONFIG_LOCALE ;
855+ changed |= ActivityInfo .CONFIG_LAYOUT_DIRECTION ;
825856 }
826857 if (delta .touchscreen != TOUCHSCREEN_UNDEFINED
827858 && touchscreen != delta .touchscreen ) {
@@ -851,8 +882,10 @@ public int diff(Configuration delta) {
851882 && orientation != delta .orientation ) {
852883 changed |= ActivityInfo .CONFIG_ORIENTATION ;
853884 }
854- if (delta .screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
855- && screenLayout != delta .screenLayout ) {
885+ if (getScreenLayoutNoDirection (delta .screenLayout ) !=
886+ (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED )
887+ && getScreenLayoutNoDirection (screenLayout ) !=
888+ getScreenLayoutNoDirection (delta .screenLayout )) {
856889 changed |= ActivityInfo .CONFIG_SCREEN_LAYOUT ;
857890 }
858891 if (delta .uiMode != (UI_MODE_TYPE_UNDEFINED |UI_MODE_NIGHT_UNDEFINED )
@@ -875,7 +908,7 @@ public int diff(Configuration delta) {
875908 && densityDpi != delta .densityDpi ) {
876909 changed |= ActivityInfo .CONFIG_DENSITY ;
877910 }
878-
911+
879912 return changed ;
880913 }
881914
@@ -963,7 +996,6 @@ public void writeToParcel(Parcel dest, int flags) {
963996 dest .writeInt (compatScreenWidthDp );
964997 dest .writeInt (compatScreenHeightDp );
965998 dest .writeInt (compatSmallestScreenWidthDp );
966- dest .writeInt (layoutDirection );
967999 dest .writeInt (seq );
9681000 }
9691001
@@ -992,7 +1024,6 @@ public void readFromParcel(Parcel source) {
9921024 compatScreenWidthDp = source .readInt ();
9931025 compatScreenHeightDp = source .readInt ();
9941026 compatSmallestScreenWidthDp = source .readInt ();
995- layoutDirection = source .readInt ();
9961027 seq = source .readInt ();
9971028 }
9981029
@@ -1100,4 +1131,50 @@ public int hashCode() {
11001131 result = 31 * result + densityDpi ;
11011132 return result ;
11021133 }
1134+
1135+ /**
1136+ * Set the locale. This is the preferred way for setting up the locale (instead of using the
1137+ * direct accessor). This will also set the userLocale and layout direction according to
1138+ * the locale.
1139+ *
1140+ * @param loc The locale. Can be null.
1141+ */
1142+ public void setLocale (Locale loc ) {
1143+ locale = loc ;
1144+ userSetLocale = true ;
1145+ setLayoutDirection (locale );
1146+ }
1147+
1148+ /**
1149+ * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or
1150+ * {@link View#LAYOUT_DIRECTION_RTL}.
1151+ *
1152+ * @return the layout direction
1153+ */
1154+ public int getLayoutDirection () {
1155+ // We need to substract one here as the configuration values are using "0" as undefined thus
1156+ // having LRT set to "1" and RTL set to "2"
1157+ return ((screenLayout &SCREENLAYOUT_LAYOUTDIR_MASK ) >> SCREENLAYOUT_LAYOUTDIR_SHIFT ) - 1 ;
1158+ }
1159+
1160+ /**
1161+ * Set the layout direction from the Locale.
1162+ *
1163+ * @param locale The Locale. If null will set the layout direction to
1164+ * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
1165+ * corresponding to the Locale.
1166+ *
1167+ * @see {@link View#LAYOUT_DIRECTION_LTR} and {@link View#LAYOUT_DIRECTION_RTL}
1168+ */
1169+ public void setLayoutDirection (Locale locale ) {
1170+ // There is a "1" difference between the configuration values for
1171+ // layout direction and View constants for layout direction, just add "1".
1172+ final int layoutDirection = 1 + LocaleUtil .getLayoutDirectionFromLocale (locale );
1173+ screenLayout = (screenLayout &~SCREENLAYOUT_LAYOUTDIR_MASK )|
1174+ (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT );
1175+ }
1176+
1177+ private static int getScreenLayoutNoDirection (int screenLayout ) {
1178+ return screenLayout &~SCREENLAYOUT_LAYOUTDIR_MASK ;
1179+ }
11031180}
0 commit comments