diff options
| author | Roozbeh Pournader <roozbeh@google.com> | 2017-04-11 16:23:45 -0700 |
|---|---|---|
| committer | Roozbeh Pournader <roozbeh@google.com> | 2017-04-12 14:19:02 -0700 |
| commit | e740fd8d7b624d7bcd99961ae515b8d0dd9090cb (patch) | |
| tree | c36a4b6bac298d957ae46043283d6470672a40a1 /core/java/android/widget | |
| parent | 88ab6c1304e3f9a2b1d96deece34bb7cbec27d8f (diff) | |
Switch i18n listeners to use IME hint locales
Previously, the i18n listeners were keyed off the text locales of the
TextView. This could create some unanticipated backward
compatibility headaches. The IME hint locales seems to be a better
match, since they are supposed to be used for input.
Fixes: 37249649
Fixes: 37133729
Fixes: 37222714
Bug: https://code.google.com/p/android/issues/detail?id=2626
Bug: 8319249
Bug: 33276673
Bug: 34394455
Bug: 37160895
Test: Updated and added CTS tests pass
Change-Id: If8a115f3e30ff1601dee426a504984e2ce24a776
Diffstat (limited to 'core/java/android/widget')
| -rw-r--r-- | core/java/android/widget/TextView.java | 76 |
1 files changed, 62 insertions, 14 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index fcab7035e60f..d4967b4f8380 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -16,7 +16,6 @@ package android.widget; -import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH; import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX; import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY; @@ -59,6 +58,7 @@ import android.graphics.drawable.Drawable; import android.graphics.fonts.FontVariationAxis; import android.icu.text.DecimalFormatSymbols; import android.os.AsyncTask; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.LocaleList; import android.os.Parcel; @@ -408,7 +408,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public Drawables(Context context) { final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; - mIsRtlCompatibilityMode = targetSdkVersion < JELLY_BEAN_MR1 + mIsRtlCompatibilityMode = targetSdkVersion < VERSION_CODES.JELLY_BEAN_MR1 || !context.getApplicationInfo().hasRtlSupport(); mOverride = false; } @@ -1363,7 +1363,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD); mUseInternationalizedInput = - context.getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O; + context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.O; if (inputMethod != null) { Class<?> c; @@ -1408,7 +1408,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } else if (numeric != 0) { createEditorIfNeeded(); mEditor.mKeyListener = DigitsKeyListener.getInstance( - mUseInternationalizedInput ? getTextLocale() : null, + null, // locale (numeric & SIGNED) != 0, (numeric & DECIMAL) != 0); inputType = mEditor.mKeyListener.getInputType(); @@ -3400,11 +3400,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mTextPaint.getTextLocales(); } - private void changeListenerLocaleTo(@NonNull Locale locale) { + private void changeListenerLocaleTo(@Nullable Locale locale) { if (mListenerChanged) { // If a listener has been explicitly set, don't change it. We may break something. return; } + // The following null check is not absolutely necessary since all calling points of + // changeListenerLocaleTo() guarantee a non-null mEditor at the moment. But this is left + // here in case others would want to call this method in the future. if (mEditor != null) { KeyListener listener = mEditor.mKeyListener; if (listener instanceof DigitsKeyListener) { @@ -3418,8 +3421,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } else { return; } + final boolean wasPasswordType = isPasswordInputType(mEditor.mInputType); setKeyListenerOnly(listener); setInputTypeFromEditor(); + if (wasPasswordType) { + final int newInputClass = mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS; + if (newInputClass == EditorInfo.TYPE_CLASS_TEXT) { + mEditor.mInputType |= EditorInfo.TYPE_TEXT_VARIATION_PASSWORD; + } else if (newInputClass == EditorInfo.TYPE_CLASS_NUMBER) { + mEditor.mInputType |= EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD; + } + } } } @@ -3434,7 +3446,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void setTextLocale(@NonNull Locale locale) { mLocalesChanged = true; mTextPaint.setTextLocale(locale); - changeListenerLocaleTo(locale); if (mLayout != null) { nullLayouts(); requestLayout(); @@ -3456,7 +3467,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void setTextLocales(@NonNull @Size(min = 1) LocaleList locales) { mLocalesChanged = true; mTextPaint.setTextLocales(locales); - changeListenerLocaleTo(locales.get(0)); if (mLayout != null) { nullLayouts(); requestLayout(); @@ -3468,9 +3478,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (!mLocalesChanged) { - final LocaleList locales = LocaleList.getDefault(); - mTextPaint.setTextLocales(locales); - changeListenerLocaleTo(locales.get(0)); + mTextPaint.setTextLocales(LocaleList.getDefault()); if (mLayout != null) { nullLayouts(); requestLayout(); @@ -5586,6 +5594,29 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mEditor.mInputType = type; } + /** + * @return {@code null} if the key listener should use pre-O (locale-independent). Otherwise + * a {@code Locale} object that can be used to customize key various listeners. + * @see DateKeyListener#getInstance(Locale) + * @see DateTimeKeyListener#getInstance(Locale) + * @see DigitsKeyListener#getInstance(Locale) + * @see TimeKeyListener#getInstance(Locale) + */ + @Nullable + private Locale getCustomLocaleForKeyListenerOrNull() { + if (!mUseInternationalizedInput) { + // If the application does not target O, stick to the previous behavior. + return null; + } + final LocaleList locales = getImeHintLocales(); + if (locales == null) { + // If the application does not explicitly specify IME hint locale, also stick to the + // previous behavior. + return null; + } + return locales.get(0); + } + private void setInputType(int type, boolean direct) { final int cls = type & EditorInfo.TYPE_MASK_CLASS; KeyListener input; @@ -5603,15 +5634,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } input = TextKeyListener.getInstance(autotext, cap); } else if (cls == EditorInfo.TYPE_CLASS_NUMBER) { + final Locale locale = getCustomLocaleForKeyListenerOrNull(); input = DigitsKeyListener.getInstance( - mUseInternationalizedInput ? getTextLocale() : null, + locale, (type & EditorInfo.TYPE_NUMBER_FLAG_SIGNED) != 0, (type & EditorInfo.TYPE_NUMBER_FLAG_DECIMAL) != 0); - if (mUseInternationalizedInput) { - type = input.getInputType(); // Override type, if necessary for i18n. + if (locale != null) { + // Override type, if necessary for i18n. + int newType = input.getInputType(); + final int newClass = newType & EditorInfo.TYPE_MASK_CLASS; + if (newClass != EditorInfo.TYPE_CLASS_NUMBER) { + // The class is different from the original class. So we need to override + // 'type'. But we want to keep the password flag if it's there. + if ((type & EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD) != 0) { + newType |= EditorInfo.TYPE_TEXT_VARIATION_PASSWORD; + } + type = newType; + } } } else if (cls == EditorInfo.TYPE_CLASS_DATETIME) { - final Locale locale = mUseInternationalizedInput ? getTextLocale() : null; + final Locale locale = getCustomLocaleForKeyListenerOrNull(); switch (type & EditorInfo.TYPE_MASK_VARIATION) { case EditorInfo.TYPE_DATETIME_VARIATION_DATE: input = DateKeyListener.getInstance(locale); @@ -5884,6 +5926,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Change "hint" locales associated with the text view, which will be reported to an IME with * {@link EditorInfo#hintLocales} when it has focus. * + * Starting with Android O, this also causes internationalized listeners to be created (or + * change locale) based on the first locale in the input locale list. + * * <p><strong>Note:</strong> If you want new "hint" to take effect immediately you need to * call {@link InputMethodManager#restartInput(View)}.</p> * @param hintLocales List of the languages that the user is supposed to switch to no matter @@ -5895,6 +5940,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener createEditorIfNeeded(); mEditor.createInputContentTypeIfNeeded(); mEditor.mInputContentType.imeHintLocales = hintLocales; + if (mUseInternationalizedInput) { + changeListenerLocaleTo(hintLocales == null ? null : hintLocales.get(0)); + } } /** |
