Permalink
Browse files

Clarify the purpose of EditorInfo#hintLocales.

During the initial attempt to support automatic language switching in
LatinIME, it turns out that the current EditorInfo#locales is difficult
to use and even confusing in some situations.  Based on that
experience, this CL changes as follows:

* Rename EditorInfo#locales to EditorInfo#hintLocales:
  This is mainly to avoid possible confusion when to set this.  We want
  to make it clear that having non-empty LocaleList there is a clear
  signal that the user would switch to certain languages regardless of
  the currently selected input method subtype.

* Make EditorInfo#hintLocales nullable:
  Previously marshaling EditorInfor causes NPE when
  EditorInfo#hintLocales is null.  This CL relaxes such a restriction.

* Introduce TextView#{set, get}ImeHintLocales():
  In the previous implementation [1], we just copied
  TextView#getTextLocales() into EditorInfo.  This is, however, does not
  work well because it is no more or less than the default value.  If
  LatinIME supports automatic language switching, having the default
  value in EditorInfo actually means that whenever you focus in a new
  text field, the keyboard language is reset to the default locale.
  In order to make this "hint" useful for IME developers, this "hint"
  should be specified only when the application developers are confident
  to do so.

  [1]: I738ffaaf07091d8b980f8bfc6e16227fcb85a96a
       0445fdf

Bug: 22859862
Change-Id: I0a730011874ea8d01e50624ed3f1ecd197d05f94
  • Loading branch information...
1 parent 88f0430 commit d469f2122edf7662dbe8c9c39269064c0265b520 @yukawa yukawa committed Jan 21, 2016
View
@@ -43584,14 +43584,14 @@ package android.view.inputmethod {
field public android.os.Bundle extras;
field public int fieldId;
field public java.lang.String fieldName;
+ field public android.util.LocaleList hintLocales;
field public java.lang.CharSequence hintText;
field public int imeOptions;
field public int initialCapsMode;
field public int initialSelEnd;
field public int initialSelStart;
field public int inputType;
field public java.lang.CharSequence label;
- field public android.util.LocaleList locales;
field public java.lang.String packageName;
field public java.lang.String privateImeOptions;
}
@@ -46838,6 +46838,7 @@ package android.widget {
method public int getHyphenationFrequency();
method public int getImeActionId();
method public java.lang.CharSequence getImeActionLabel();
+ method public android.util.LocaleList getImeHintLocales();
method public int getImeOptions();
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
@@ -46944,6 +46945,7 @@ package android.widget {
method public void setHorizontallyScrolling(boolean);
method public void setHyphenationFrequency(int);
method public void setImeActionLabel(java.lang.CharSequence, int);
+ method public void setImeHintLocales(android.util.LocaleList);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -45985,14 +45985,14 @@ package android.view.inputmethod {
field public android.os.Bundle extras;
field public int fieldId;
field public java.lang.String fieldName;
+ field public android.util.LocaleList hintLocales;
field public java.lang.CharSequence hintText;
field public int imeOptions;
field public int initialCapsMode;
field public int initialSelEnd;
field public int initialSelStart;
field public int inputType;
field public java.lang.CharSequence label;
- field public android.util.LocaleList locales;
field public java.lang.String packageName;
field public java.lang.String privateImeOptions;
}
@@ -49565,6 +49565,7 @@ package android.widget {
method public int getHyphenationFrequency();
method public int getImeActionId();
method public java.lang.CharSequence getImeActionLabel();
+ method public android.util.LocaleList getImeHintLocales();
method public int getImeOptions();
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
@@ -49671,6 +49672,7 @@ package android.widget {
method public void setHorizontallyScrolling(boolean);
method public void setHyphenationFrequency(int);
method public void setImeActionLabel(java.lang.CharSequence, int);
+ method public void setImeHintLocales(android.util.LocaleList);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -43600,14 +43600,14 @@ package android.view.inputmethod {
field public android.os.Bundle extras;
field public int fieldId;
field public java.lang.String fieldName;
+ field public android.util.LocaleList hintLocales;
field public java.lang.CharSequence hintText;
field public int imeOptions;
field public int initialCapsMode;
field public int initialSelEnd;
field public int initialSelStart;
field public int inputType;
field public java.lang.CharSequence label;
- field public android.util.LocaleList locales;
field public java.lang.String packageName;
field public java.lang.String privateImeOptions;
}
@@ -46854,6 +46854,7 @@ package android.widget {
method public int getHyphenationFrequency();
method public int getImeActionId();
method public java.lang.CharSequence getImeActionLabel();
+ method public android.util.LocaleList getImeHintLocales();
method public int getImeOptions();
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
@@ -46960,6 +46961,7 @@ package android.widget {
method public void setHorizontallyScrolling(boolean);
method public void setHyphenationFrequency(int);
method public void setImeActionLabel(java.lang.CharSequence, int);
+ method public void setImeHintLocales(android.util.LocaleList);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -16,6 +16,7 @@
package android.view.inputmethod;
+import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -341,20 +342,26 @@
public Bundle extras;
/**
- * Additional context information that tells what languages are expected by the user.
+ * List of the languages that the user is supposed to switch to no matter what input method
+ * subtype is currently used. This special "hint" can be used mainly for, but not limited to,
+ * multilingual users who want IMEs to switch language context automatically.
*
- * <p><strong>IME authors:</strong> Possible use cases for IME developers would be:</p>
- * <ul>
- * <li>Automatically switching keyboard layout.</li>
- * <li>Changing language model for better typing experience.</li>
- * </ul>
+ * <p>{@code null} means that no special language "hint" is needed.</p>
*
- * <p><strong>Editor authors:</strong> Providing this context information can help IMEs to
- * improve text input experience. For example, chat applications can remember what language is
- * used in the last conversation for each chat session, and put the last used language at the
- * top of {@link #locales}.</p>
+ * <p><strong>Editor authors:</strong> Specify this only when you are confident that the user
+ * will switch to certain languages in this context no matter what input method subtype is
+ * currently selected. Otherwise, keep this {@code null}. Explicit user actions and/or
+ * preferences would be good signals to specify this special "hint", For example, a chat
+ * application may be able to put the last used language at the top of {@link #hintLocales}
+ * based on whom the user is going to talk, by remembering what language is used in the last
+ * conversation. Do not specify {@link android.widget.TextView#getTextLocales()} only because
+ * it is used for text rendering.</p>
+ *
+ * @see android.widget.TextView#setImeHintLocales(LocaleList)
+ * @see android.widget.TextView#getImeHintLocales()
*/
- public LocaleList locales = LocaleList.getEmptyLocaleList();
+ @Nullable
+ public LocaleList hintLocales = null;
/**
* Ensure that the data in this EditorInfo is compatible with an application
@@ -410,7 +417,7 @@ public void dump(Printer pw, String prefix) {
+ " fieldId=" + fieldId
+ " fieldName=" + fieldName);
pw.println(prefix + "extras=" + extras);
- pw.println(prefix + "locales=" + locales);
+ pw.println(prefix + "hintLocales=" + hintLocales);
}
/**
@@ -434,7 +441,11 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(fieldId);
dest.writeString(fieldName);
dest.writeBundle(extras);
- locales.writeToParcel(dest, flags);
+ if (hintLocales != null) {
+ hintLocales.writeToParcel(dest, flags);
+ } else {
+ LocaleList.getEmptyLocaleList().writeToParcel(dest, flags);
+ }
}
/**
@@ -458,7 +469,8 @@ public EditorInfo createFromParcel(Parcel source) {
res.fieldId = source.readInt();
res.fieldName = source.readString();
res.extras = source.readBundle();
- res.locales = LocaleList.CREATOR.createFromParcel(source);
+ LocaleList hintLocales = LocaleList.CREATOR.createFromParcel(source);
+ res.hintLocales = hintLocales.isEmpty() ? null : hintLocales;
return res;
}
@@ -69,6 +69,7 @@
import android.text.style.TextAppearanceSpan;
import android.text.style.URLSpan;
import android.util.DisplayMetrics;
+import android.util.LocaleList;
import android.util.Log;
import android.util.SparseArray;
import android.view.ActionMode;
@@ -5299,6 +5300,7 @@ public void update(int x, int y, int w, int h, boolean force) {
Bundle extras;
OnEditorActionListener onEditorActionListener;
boolean enterDown;
+ LocaleList imeHintLocales;
}
static class InputMethodState {
@@ -4992,6 +4992,35 @@ public Bundle getInputExtras(boolean create) {
}
/**
+ * Change "hint" locales associated with the text view, which will be reported to an IME with
+ * {@link EditorInfo#hintLocales} when it has focus.
+ *
+ * <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
+ * what input method subtype is currently used. Set {@code null} to clear the current "hint".
+ * @see #getImeHIntLocales()
+ * @see android.view.inputmethod.EditorInfo#hintLocales
+ */
+ public void setImeHintLocales(@Nullable LocaleList hintLocales) {
+ createEditorIfNeeded();
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.imeHintLocales = hintLocales;
+ }
+
+ /**
+ * @return The current languages list "hint". {@code null} when no "hint" is available.
+ * @see #setImeHintLocales(LocaleList)
+ * @see android.view.inputmethod.EditorInfo#hintLocales
+ */
+ @Nullable
+ public LocaleList getImeHintLocales() {
+ if (mEditor == null) { return null; }
+ if (mEditor.mInputContentType == null) { return null; }
+ return mEditor.mInputContentType.imeHintLocales;
+ }
+
+ /**
* Returns the error message that was set to be displayed with
* {@link #setError}, or <code>null</code> if no error was set
* or if it the error was cleared by the widget after user input.
@@ -6411,8 +6440,10 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.actionLabel = mEditor.mInputContentType.imeActionLabel;
outAttrs.actionId = mEditor.mInputContentType.imeActionId;
outAttrs.extras = mEditor.mInputContentType.extras;
+ outAttrs.hintLocales = mEditor.mInputContentType.imeHintLocales;
} else {
outAttrs.imeOptions = EditorInfo.IME_NULL;
+ outAttrs.hintLocales = null;
}
if (focusSearch(FOCUS_DOWN) != null) {
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
@@ -6440,9 +6471,6 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
}
outAttrs.hintText = mHint;
- // LocaleList is designed to be immutable. This is theoretically equivalent to copy
- // the snapshot of the current text locales.
- outAttrs.locales = getTextLocales();
if (mText instanceof Editable) {
InputConnection ic = new EditableInputConnection(this);
outAttrs.initialSelStart = getSelectionStart();

0 comments on commit d469f21

Please sign in to comment.