下面列出了怎么用android.view.inputmethod.InputMethodSubtype的API类实例代码及写法,或者点击链接到github查看源代码。
private void initInternal(final Context context) {
if (isInitialized()) {
return;
}
mImmService = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
mContext = context;
mInputMethodInfoCache = new InputMethodInfoCache(
mImmService, context.getPackageName());
// Initialize additional subtypes.
SubtypeLocaleUtils.init(context);
final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes();
mImmService.setAdditionalInputMethodSubtypes(
getInputMethodIdOfThisIme(), additionalSubtypes);
// Initialize the current input method subtype and the shortcut IME.
refreshSubtypeCaches();
}
public void switchSubtype(final IBinder token, final RichInputMethodManager richImm) {
final InputMethodSubtype currentSubtype = richImm.getInputMethodManager()
.getCurrentInputMethodSubtype();
final InputMethodSubtype lastActiveSubtype = mLastActiveSubtype;
final boolean currentSubtypeHasBeenUsed = mCurrentSubtypeHasBeenUsed;
if (currentSubtypeHasBeenUsed) {
mLastActiveSubtype = currentSubtype;
mCurrentSubtypeHasBeenUsed = false;
}
if (currentSubtypeHasBeenUsed
&& richImm.checkIfSubtypeBelongsToThisImeAndEnabled(lastActiveSubtype)
&& !currentSubtype.equals(lastActiveSubtype)) {
richImm.setInputMethodAndSubtype(token, lastActiveSubtype);
return;
}
richImm.switchToNextInputMethod(token, true /* onlyCurrentIme */);
}
@Override
public void onSaveCustomInputStyle(final CustomInputStylePreference stylePref) {
final InputMethodSubtype subtype = stylePref.getSubtype();
if (!stylePref.hasBeenModified()) {
return;
}
if (findDuplicatedSubtype(subtype) == null) {
mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
return;
}
// Saved subtype is duplicated.
final PreferenceGroup group = getPreferenceScreen();
group.removePreference(stylePref);
stylePref.revert();
group.addPreference(stylePref);
showSubtypeAlreadyExistsToast(subtype);
}
public void testHinglishActionLabel() {
final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
final Locale hi_ZZ = new Locale("hi", "ZZ");
final InputMethodSubtype hiLatn = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
hi_ZZ.toString(), SubtypeLocaleUtils.QWERTY);
// This is a preliminary subtype and may not exist.
if (hiLatn == null) {
return;
}
// An action label should be displayed in subtype's locale regardless of the system locale.
doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, new Locale("hi"));
doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.US);
doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.FRENCH);
doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.ITALIAN);
doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.JAPANESE);
}
@Nonnull
public static RichInputMethodSubtype getNoLanguageSubtype() {
RichInputMethodSubtype noLanguageSubtype = sNoLanguageSubtype;
if (noLanguageSubtype == null) {
final InputMethodSubtype rawNoLanguageSubtype = RichInputMethodManager.getInstance()
.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
if (rawNoLanguageSubtype != null) {
noLanguageSubtype = new RichInputMethodSubtype(rawNoLanguageSubtype);
}
}
if (noLanguageSubtype != null) {
sNoLanguageSubtype = noLanguageSubtype;
return noLanguageSubtype;
}
Log.w(TAG, "Can't find any language with QWERTY subtype");
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+ DUMMY_NO_LANGUAGE_SUBTYPE);
return DUMMY_NO_LANGUAGE_SUBTYPE;
}
public void setSubtype(final InputMethodSubtype subtype) {
mPreviousSubtype = mSubtype;
mSubtype = subtype;
if (isIncomplete()) {
setTitle(null);
setDialogTitle(R.string.add_style);
setKey(KEY_NEW_SUBTYPE);
} else {
final String displayName =
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
setTitle(displayName);
setDialogTitle(displayName);
setKey(KEY_PREFIX + subtype.getLocale() + "_"
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype));
}
}
private static String getSubtypeDisplayNameInternal(final InputMethodSubtype subtype,
final Locale displayLocale) {
final String replacementString = getReplacementString(subtype, displayLocale);
// TODO: rework this for multi-lingual subtypes
final int nameResId = subtype.getNameResId();
final RunInLocale<String> getSubtypeName = new RunInLocale<String>() {
@Override
protected String job(final Resources res) {
try {
return res.getString(nameResId, replacementString);
} catch (Resources.NotFoundException e) {
// TODO: Remove this catch when InputMethodManager.getCurrentInputMethodSubtype
// is fixed.
Log.w(TAG, "Unknown subtype: mode=" + subtype.getMode()
+ " nameResId=" + subtype.getNameResId()
+ " locale=" + subtype.getLocale()
+ " extra=" + subtype.getExtraValue()
+ "\n" + DebugLogUtils.getStackTrace());
return "";
}
}
};
return StringUtils.capitalizeFirstCodePoint(
getSubtypeName.runInLocale(sResources, displayLocale), displayLocale);
}
public void testIsRtlLanguage() {
// Known Right-to-Left language subtypes.
final InputMethodSubtype ARABIC = mRichImm
.findSubtypeByLocaleAndKeyboardLayoutSet("ar", "arabic");
assertNotNull("Arabic", ARABIC);
final InputMethodSubtype FARSI = mRichImm
.findSubtypeByLocaleAndKeyboardLayoutSet("fa", "farsi");
assertNotNull("Farsi", FARSI);
final InputMethodSubtype HEBREW = mRichImm
.findSubtypeByLocaleAndKeyboardLayoutSet("iw", "hebrew");
assertNotNull("Hebrew", HEBREW);
for (final RichInputMethodSubtype subtype : mSubtypesList) {
final InputMethodSubtype rawSubtype = subtype.getRawSubtype();
final String subtypeName = SubtypeLocaleUtils
.getSubtypeDisplayNameInSystemLocale(rawSubtype);
if (rawSubtype.equals(ARABIC) || rawSubtype.equals(FARSI)
|| rawSubtype.equals(HEBREW)) {
assertTrue(subtypeName, subtype.isRtlSubtype());
} else {
assertFalse(subtypeName, subtype.isRtlSubtype());
}
}
}
private static void assertEnUsDvorak(InputMethodSubtype subtype) {
assertEquals("en_US", subtype.getLocale());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
assertEquals(EXTRA_VALUE_EN_US_DVORAK_KITKAT, subtype.getExtraValue());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
assertEquals(EXTRA_VALUE_EN_US_DVORAK_JELLY_BEAN, subtype.getExtraValue());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
assertEquals(EXTRA_VALUE_EN_US_DVORAK_ICS, subtype.getExtraValue());
}
assertTrue(subtype.containsExtraValueKey(ASCII_CAPABLE));
assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapable(subtype));
// TODO: Enable following test
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapableWithAPI(subtype));
// }
assertTrue(subtype.containsExtraValueKey(EMOJI_CAPABLE));
assertTrue(subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE));
assertEquals("dvorak", subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET));
assertEquals("Dvorak", subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME));
assertEquals(KEYBOARD_MODE, subtype.getMode());
assertEquals(SUBTYPE_ID_EN_US_DVORAK, subtype.hashCode());
}
private boolean switchToNextInputMethodAndSubtype(final IBinder token) {
final InputMethodManager imm = mImmWrapper.mImm;
final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
final int currentIndex = getImiIndexInList(getInputMethodInfoOfThisIme(), enabledImis);
if (currentIndex == INDEX_NOT_FOUND) {
Log.w(TAG, "Can't find current IME in enabled IMEs: IME package="
+ getInputMethodInfoOfThisIme().getPackageName());
return false;
}
final InputMethodInfo nextImi = getNextNonAuxiliaryIme(currentIndex, enabledImis);
final List<InputMethodSubtype> enabledSubtypes = getEnabledInputMethodSubtypeList(nextImi,
true /* allowsImplicitlySelectedSubtypes */);
if (enabledSubtypes.isEmpty()) {
// The next IME has no subtype.
imm.setInputMethod(token, nextImi.getId());
return true;
}
final InputMethodSubtype firstSubtype = enabledSubtypes.get(0);
imm.setInputMethodAndSubtype(token, nextImi.getId(), firstSubtype);
return true;
}
public SubtypeLocaleAdapter(final Context context) {
super(context, android.R.layout.simple_spinner_item);
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
final TreeSet<SubtypeLocaleItem> items = new TreeSet<>();
final InputMethodInfo imi = RichInputMethodManager.getInstance()
.getInputMethodInfoOfThisIme();
final int count = imi.getSubtypeCount();
for (int i = 0; i < count; i++) {
final InputMethodSubtype subtype = imi.getSubtypeAt(i);
if (DEBUG_SUBTYPE_ID) {
Log.d(TAG_SUBTYPE, String.format("%-6s 0x%08x %11d %s",
subtype.getLocale(), subtype.hashCode(), subtype.hashCode(),
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype)));
}
if (subtype.isAsciiCapable()) {
items.add(new SubtypeLocaleItem(subtype));
}
}
// TODO: Should filter out already existing combinations of locale and layout.
addAll(items);
}
public void setSubtype(final InputMethodSubtype subtype) {
mPreviousSubtype = mSubtype;
mSubtype = subtype;
if (isIncomplete()) {
setTitle(null);
setDialogTitle(R.string.add_style);
setKey(KEY_NEW_SUBTYPE);
} else {
final String displayName =
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
setTitle(displayName);
setDialogTitle(displayName);
setKey(KEY_PREFIX + subtype.getLocale() + "_"
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype));
}
}
private void initInternal(final Context context) {
if (isInitialized()) {
return;
}
mImmService = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
mContext = context;
mInputMethodInfoCache = new InputMethodInfoCache(
mImmService, context.getPackageName());
// Initialize additional subtypes.
SubtypeLocaleUtils.init(context);
final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes();
mImmService.setAdditionalInputMethodSubtypes(
getInputMethodIdOfThisIme(), additionalSubtypes);
// Initialize the current input method subtype and the shortcut IME.
refreshSubtypeCaches();
}
void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
super.onStartInput(editorInfo, restarting);
// If the primary hint language does not match the current subtype language, then try
// to switch to the primary hint language.
// TODO: Support all the locales in EditorInfo#hintLocales.
final Locale primaryHintLocale = EditorInfoCompatUtils.getPrimaryHintLocale(editorInfo);
if (primaryHintLocale == null) {
return;
}
final InputMethodSubtype newSubtype = mRichImm.findSubtypeByLocale(primaryHintLocale);
if (newSubtype == null || newSubtype.equals(mRichImm.getCurrentSubtype().getRawSubtype())) {
return;
}
mHandler.postSwitchLanguage(newSubtype);
}
@Override
public void onAddCustomInputStyle(final CustomInputStylePreference stylePref) {
mIsAddingNewSubtype = false;
final InputMethodSubtype subtype = stylePref.getSubtype();
if (findDuplicatedSubtype(subtype) == null) {
mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
mSubtypePreferenceKeyForSubtypeEnabler = stylePref.getKey();
mSubtypeEnablerNotificationDialog = createDialog();
mSubtypeEnablerNotificationDialog.show();
return;
}
// Newly added subtype is duplicated.
final PreferenceGroup group = getPreferenceScreen();
group.removePreference(stylePref);
showSubtypeAlreadyExistsToast(subtype);
}
protected void doTestActionKey(final String tag, final InputMethodSubtype subtype,
final EditorInfo editorInfo, final ExpectedActionKey expectedKey) {
// Test text layouts.
editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, expectedKey);
assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, expectedKey);
assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, expectedKey);
// Test phone number layouts.
assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, expectedKey);
assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, expectedKey);
// Test normal number layout.
assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, expectedKey);
// Test number password layout.
editorInfo.inputType =
InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
assertActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, expectedKey);
}
private void initInternal(final Context context) {
if (isInitialized()) {
return;
}
mImmWrapper = new InputMethodManagerCompatWrapper(context);
mContext = context;
mInputMethodInfoCache = new InputMethodInfoCache(
mImmWrapper.mImm, context.getPackageName());
// Initialize additional subtypes.
SubtypeLocaleUtils.init(context);
final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes();
mImmWrapper.mImm.setAdditionalInputMethodSubtypes(
getInputMethodIdOfThisIme(), additionalSubtypes);
// Initialize the current input method subtype and the shortcut IME.
refreshSubtypeCaches();
}
public void onSubtypeChanged(final InputMethodSubtype newSubtype) {
updateCurrentSubtype(newSubtype);
updateShortcutIme();
if (DEBUG) {
Log.w(TAG, "onSubtypeChanged: " + mCurrentRichInputMethodSubtype.getNameForLogging());
}
}
public static String createPrefSubtypes(final InputMethodSubtype[] subtypes) {
if (subtypes == null || subtypes.length == 0) {
return "";
}
final StringBuilder sb = new StringBuilder();
for (final InputMethodSubtype subtype : subtypes) {
if (sb.length() > 0) {
sb.append(PREF_SUBTYPE_SEPARATOR);
}
sb.append(getPrefSubtype(subtype));
}
return sb.toString();
}
public InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(final String localeString,
final String keyboardLayoutSetName) {
final InputMethodInfo myImi = getInputMethodInfoOfThisIme();
final int count = myImi.getSubtypeCount();
for (int i = 0; i < count; i++) {
final InputMethodSubtype subtype = myImi.getSubtypeAt(i);
final String layoutName = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
if (localeString.equals(subtype.getLocale())
&& keyboardLayoutSetName.equals(layoutName)) {
return subtype;
}
}
return null;
}
private static int getSubtypeIndexInList(final InputMethodSubtype subtype,
final List<InputMethodSubtype> subtypes) {
final int count = subtypes.size();
for (int index = 0; index < count; index++) {
final InputMethodSubtype ims = subtypes.get(index);
if (ims.equals(subtype)) {
return index;
}
}
return INDEX_NOT_FOUND;
}
public void testActionCustom() {
for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
final EditorInfo editorInfo = new EditorInfo();
editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
editorInfo.actionLabel = "customLabel";
final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey("customLabel");
doTestActionKey(tag, subtype, editorInfo, expectedKey);
}
}
@Override
protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
final EditorInfo emailField = new EditorInfo();
emailField.inputType =
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI;
return super.createKeyboardLayoutSet(
subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled,
splitLayoutEnabled);
}
public InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(final String localeString,
final String keyboardLayoutSetName) {
final InputMethodInfo myImi = getInputMethodInfoOfThisIme();
final int count = myImi.getSubtypeCount();
for (int i = 0; i < count; i++) {
final InputMethodSubtype subtype = myImi.getSubtypeAt(i);
final String layoutName = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
if (localeString.equals(subtype.getLocale())
&& keyboardLayoutSetName.equals(layoutName)) {
return subtype;
}
}
return null;
}
private void recordKeyboardLocaleUma() {
InputMethodManager imm =
(InputMethodManager) mAppContext.getSystemService(Context.INPUT_METHOD_SERVICE);
List<InputMethodInfo> ims = imm.getEnabledInputMethodList();
ArrayList<String> uniqueLanguages = new ArrayList<>();
for (InputMethodInfo method : ims) {
List<InputMethodSubtype> submethods =
imm.getEnabledInputMethodSubtypeList(method, true);
for (InputMethodSubtype submethod : submethods) {
if (submethod.getMode().equals("keyboard")) {
String language = submethod.getLocale().split("_")[0];
if (!uniqueLanguages.contains(language)) {
uniqueLanguages.add(language);
}
}
}
}
RecordHistogram.recordCountHistogram("InputMethod.ActiveCount", uniqueLanguages.size());
InputMethodSubtype currentSubtype = imm.getCurrentInputMethodSubtype();
Locale systemLocale = Locale.getDefault();
if (currentSubtype != null && currentSubtype.getLocale() != null && systemLocale != null) {
String keyboardLanguage = currentSubtype.getLocale().split("_")[0];
boolean match = systemLocale.getLanguage().equalsIgnoreCase(keyboardLanguage);
RecordHistogram.recordBooleanHistogram("InputMethod.MatchesSystemLanguage", match);
}
}
@Nonnull
private static String getReplacementString(@Nonnull final InputMethodSubtype subtype,
@Nonnull final Locale displayLocale) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
}
return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
}
public CustomInputStylePreference(final Context context, final InputMethodSubtype subtype,
final Listener proxy) {
super(context, null);
setDialogLayoutResource(R.layout.additional_subtype_dialog);
setPersistent(false);
mProxy = proxy;
setSubtype(subtype);
}
public boolean checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(
final InputMethodSubtype subtype) {
final boolean subtypeEnabled = checkIfSubtypeBelongsToThisImeAndEnabled(subtype);
final boolean subtypeExplicitlyEnabled = checkIfSubtypeBelongsToList(subtype,
getMyEnabledInputMethodSubtypeList(false /* allowsImplicitlySelectedSubtypes */));
return subtypeEnabled && !subtypeExplicitlyEnabled;
}
public InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(final String localeString,
final String keyboardLayoutSetName) {
final InputMethodInfo myImi = getInputMethodInfoOfThisIme();
final int count = myImi.getSubtypeCount();
for (int i = 0; i < count; i++) {
final InputMethodSubtype subtype = myImi.getSubtypeAt(i);
final String layoutName = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
if (localeString.equals(subtype.getLocale())
&& keyboardLayoutSetName.equals(layoutName)) {
return subtype;
}
}
return null;
}
@Override
public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
if (!calledFromValidUser()) {
return;
}
synchronized (mMethodMap) {
if (subtype != null) {
setInputMethodWithSubtypeId(token, id, InputMethodUtils.getSubtypeIdFromHashCode(
mMethodMap.get(id), subtype.hashCode()));
} else {
setInputMethod(token, id);
}
}
}