Support RTL layout in custom input style settings

Bug: 17322353
Change-Id: I3b211ab8729121271563a8a243558a58ee7847c2
diff --git a/java/res/layout/additional_subtype_dialog.xml b/java/res/layout/additional_subtype_dialog.xml
index f97c006..b7804f5 100644
--- a/java/res/layout/additional_subtype_dialog.xml
+++ b/java/res/layout/additional_subtype_dialog.xml
@@ -18,39 +18,60 @@
 */
 -->
 
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:columnCount="2"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:layout_marginLeft="8dip"
-    android:layout_marginRight="8dip"
-    android:padding="8dip">
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left|center_vertical"
-        style="?android:attr/textAppearanceSmall"
-        android:text="@string/subtype_locale" />
-    <Spinner
-        android:id="@+id/subtype_locale_spinner"
-        android:layout_width="wrap_content"
-        android:layout_marginLeft="8dip"
-        android:layout_marginBottom="8dip"
-        android:layout_marginTop="8dip"
-        android:layout_gravity="fill_horizontal|center_vertical"
-        android:prompt="@string/subtype_locale" />
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left|center_vertical"
-        style="?android:attr/textAppearanceSmall"
-        android:text="@string/keyboard_layout_set" />
-    <Spinner
-        android:id="@+id/keyboard_layout_set_spinner"
-        android:layout_width="wrap_content"
-        android:layout_marginLeft="8dip"
-        android:layout_marginBottom="8dip"
-        android:layout_marginTop="8dip"
-        android:layout_gravity="fill_horizontal|center_vertical"
-        android:prompt="@string/keyboard_layout_set" />
-</GridLayout>
+    android:padding="16dip">
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView
+            android:layout_width="0dp"
+            android:layout_weight="30"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|center_vertical"
+            android:gravity="start|left"
+            android:textAlignment="viewStart"
+            style="?android:attr/textAppearanceSmall"
+            android:text="@string/subtype_locale" />
+        <Spinner
+            android:id="@+id/subtype_locale_spinner"
+            android:spinnerMode="dialog"
+            android:layout_width="0dp"
+            android:layout_weight="70"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="8dip"
+            android:layout_marginBottom="8dip"
+            android:layout_marginTop="8dip"
+            android:layout_gravity="fill_horizontal|center_vertical"
+            android:gravity="start|left"
+            android:prompt="@string/subtype_locale" />
+        </LinearLayout>
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView
+            android:layout_width="0dp"
+            android:layout_weight="30"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|center_vertical"
+            android:textAlignment="viewStart"
+            style="?android:attr/textAppearanceSmall"
+            android:text="@string/keyboard_layout_set" />
+        <Spinner
+            android:id="@+id/keyboard_layout_set_spinner"
+            android:spinnerMode="dialog"
+            android:layout_width="0dp"
+            android:layout_weight="70"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="8dip"
+            android:layout_marginBottom="8dip"
+            android:layout_marginTop="8dip"
+            android:layout_gravity="fill_horizontal|center_vertical"
+            android:gravity="start|left"
+            android:prompt="@string/keyboard_layout_set" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
index afbe8c8..0f00be1 100644
--- a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
@@ -34,6 +34,9 @@
     // Note that View.setElevation(float) has been introduced in API level 21.
     private static final Method METHOD_setElevation = CompatUtils.getMethod(
             View.class, "setElevation", float.class);
+    // Note that View.setTextAlignment(int) has been introduced in API level 17.
+    private static final Method METHOD_setTextAlignment = CompatUtils.getMethod(
+            View.class, "setTextAlignment", int.class);
 
     private ViewCompatUtils() {
         // This utility class is not publicly instantiable.
@@ -56,9 +59,19 @@
     }
 
     public static void setElevation(final View view, final float elevation) {
-        if (METHOD_setElevation == null) {
-            return;
-        }
         CompatUtils.invoke(view, null, METHOD_setElevation, elevation);
     }
+
+    // These TEXT_ALIGNMENT_* constants have been introduced in API 17.
+    public static final int TEXT_ALIGNMENT_INHERIT = 0;
+    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
+    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
+    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
+    public static final int TEXT_ALIGNMENT_CENTER = 4;
+    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
+    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
+
+    public static void setTextAlignment(final View view, final int textAlignment) {
+        CompatUtils.invoke(view, null, METHOD_setTextAlignment, textAlignment);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
index 6d7f53c..d53a616 100644
--- a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
@@ -30,11 +30,14 @@
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
+import android.support.v4.view.ViewCompat;
 import android.util.Pair;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.widget.ArrayAdapter;
@@ -43,6 +46,7 @@
 import android.widget.Toast;
 
 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
+import com.android.inputmethod.compat.ViewCompatUtils;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
@@ -233,6 +237,12 @@
             mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
             mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
             mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
+            // All keyboard layout names are in the Latin script and thus left to right. That means
+            // the view would align them to the left even if the system locale is RTL, but that
+            // would look strange. To fix this, we align them to the view's start, which will be
+            // natural for any direction.
+            ViewCompatUtils.setTextAlignment(
+                    mKeyboardLayoutSetSpinner, ViewCompatUtils.TEXT_ALIGNMENT_VIEW_START);
             return v;
         }
 
@@ -398,6 +408,16 @@
     }
 
     @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View view = super.onCreateView(inflater, container, savedInstanceState);
+        // For correct display in RTL locales, we need to set the layout direction of the
+        // fragment's top view.
+        ViewCompat.setLayoutDirection(view, ViewCompat.LAYOUT_DIRECTION_LOCALE);
+        return view;
+    }
+
+    @Override
     public void onActivityCreated(final Bundle savedInstanceState) {
         final Context context = getActivity();
         mSubtypeLocaleAdapter = new SubtypeLocaleAdapter(context);
@@ -422,7 +442,7 @@
                     KEY_SUBTYPE_FOR_SUBTYPE_ENABLER);
             final SubtypePreference subtypePref = (SubtypePreference)findPreference(
                     mSubtypePreferenceKeyForSubtypeEnabler);
-            mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
+            mSubtypeEnablerNotificationDialog = createDialog();
             mSubtypeEnablerNotificationDialog.show();
         }
     }
@@ -476,7 +496,7 @@
             if (findDuplicatedSubtype(subtype) == null) {
                 mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
                 mSubtypePreferenceKeyForSubtypeEnabler = subtypePref.getKey();
-                mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
+                mSubtypeEnablerNotificationDialog = createDialog();
                 mSubtypeEnablerNotificationDialog.show();
                 return;
             }
@@ -513,7 +533,7 @@
                 localeString, keyboardLayoutSetName);
     }
 
-    private AlertDialog createDialog(final SubtypePreference subtypePref) {
+    private AlertDialog createDialog() {
         final AlertDialog.Builder builder = new AlertDialog.Builder(
                 DialogUtils.getPlatformDialogThemeContext(getActivity()));
         builder.setTitle(R.string.custom_input_styles_title)