Loading res/xml/user_dictionary_list_fragment.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="user_dict_list" android:title="@string/user_dict_settings_title" settings:controller="com.android.settings.inputmethod.UserDictionaryListPreferenceController"> </PreferenceScreen> src/com/android/settings/core/PreferenceControllerListHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ public class PreferenceControllerListHelper { List<Bundle> preferenceMetadata; try { preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId, MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER); MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER | MetadataFlag.FLAG_INCLUDE_PREF_SCREEN); } catch (IOException | XmlPullParserException e) { Log.e(TAG, "Failed to parse preference xml for getting controllers", e); return controllers; Loading src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java +16 −10 Original line number Diff line number Diff line Loading @@ -172,6 +172,7 @@ public class UserDictionaryAddWordContents { + "=? AND " + UserDictionary.Words.LOCALE + "=?"; private static final String HAS_WORD_SELECTION_ALL_LOCALES = UserDictionary.Words.WORD + "=? AND " + UserDictionary.Words.LOCALE + " is null"; private boolean hasWord(final String word, final Context context) { final Cursor cursor; // mLocale == "" indicates this is an entry for all languages. Here, mLocale can't Loading @@ -196,6 +197,7 @@ public class UserDictionaryAddWordContents { public static class LocaleRenderer { private final String mLocaleString; private final String mDescription; // LocaleString may NOT be null. public LocaleRenderer(final Context context, final String localeString) { mLocaleString = localeString; Loading @@ -207,13 +209,16 @@ public class UserDictionaryAddWordContents { mDescription = Utils.createLocaleFromString(localeString).getDisplayName(); } } @Override public String toString() { return mDescription; } public String getLocaleString() { return mLocaleString; } // "More languages..." is null ; "All languages" is the empty string. public boolean isMoreLanguages() { return null == mLocaleString; Loading @@ -229,7 +234,8 @@ public class UserDictionaryAddWordContents { // Helper method to get the list of locales to display for this word public ArrayList<LocaleRenderer> getLocalesList(final Activity activity) { final TreeSet<String> locales = UserDictionaryList.getUserDictionaryLocalesSet(activity); final TreeSet<String> locales = UserDictionaryListPreferenceController.getUserDictionaryLocalesSet(activity); // Remove our locale if it's in, because we're always gonna put it at the top locales.remove(mLocale); // mLocale may not be null final String systemLocale = Locale.getDefault().toString(); Loading src/com/android/settings/inputmethod/UserDictionaryList.java +11 −139 Original line number Diff line number Diff line Loading @@ -16,33 +16,17 @@ package com.android.settings.inputmethod; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.provider.UserDictionary; import android.support.annotation.NonNull; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; import android.text.TextUtils; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; import com.android.settings.dashboard.DashboardFragment; import java.util.List; import java.util.Locale; import java.util.TreeSet; public class UserDictionaryList extends DashboardFragment { public class UserDictionaryList extends SettingsPreferenceFragment { public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION = "android.settings.USER_DICTIONARY_SETTINGS"; private String mLocale; private static final String TAG = "UserDictionaryList"; @Override public int getMetricsCategory() { Loading @@ -50,15 +34,8 @@ public class UserDictionaryList extends SettingsPreferenceFragment { } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity())); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getActivity().getActionBar().setTitle(R.string.user_dict_settings_title); public void onAttach(Context context) { super.onAttach(context); final Intent intent = getActivity().getIntent(); final String localeFromIntent = Loading @@ -76,122 +53,17 @@ public class UserDictionaryList extends SettingsPreferenceFragment { } else { locale = null; } mLocale = locale; } @NonNull public static TreeSet<String> getUserDictionaryLocalesSet(Context context) { final Cursor cursor = context.getContentResolver().query( UserDictionary.Words.CONTENT_URI, new String[]{UserDictionary.Words.LOCALE}, null, null, null); final TreeSet<String> localeSet = new TreeSet<>(); if (cursor == null) { // The user dictionary service is not present or disabled. Return empty set. return localeSet; } try { if (cursor.moveToFirst()) { final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE); do { final String locale = cursor.getString(columnIndex); localeSet.add(null != locale ? locale : ""); } while (cursor.moveToNext()); } } finally { cursor.close(); } // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { // // For ICS, we need to show "For all languages" in case that the keyboard locale // // is different from the system locale // localeSet.add(""); // } final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); final List<InputMethodInfo> imis = imm.getEnabledInputMethodList(); for (final InputMethodInfo imi : imis) { final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList( imi, true /* allowsImplicitlySelectedSubtypes */); for (InputMethodSubtype subtype : subtypes) { final String locale = subtype.getLocale(); if (!TextUtils.isEmpty(locale)) { localeSet.add(locale); } } } // We come here after we have collected locales from existing user dictionary entries and // enabled subtypes. If we already have the locale-without-country version of the system // locale, we don't add the system locale to avoid confusion even though it's technically // correct to add it. if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) { localeSet.add(Locale.getDefault().toString()); } return localeSet; } /** * Creates the entries that allow the user to go into the user dictionary for each locale. * * @param userDictGroup The group to put the settings in. */ protected void createUserDictSettings(PreferenceGroup userDictGroup) { final Activity activity = getActivity(); userDictGroup.removeAll(); final TreeSet<String> localeSet = UserDictionaryList.getUserDictionaryLocalesSet(activity); if (mLocale != null) { // If the caller explicitly specify empty string as a locale, we'll show "all languages" // in the list. localeSet.add(mLocale); } if (localeSet.size() > 1) { // Have an "All languages" entry in the languages list if there are two or more active // languages localeSet.add(""); } if (localeSet.isEmpty()) { userDictGroup.addPreference(createUserDictionaryPreference(null, activity)); } else { for (String locale : localeSet) { userDictGroup.addPreference(createUserDictionaryPreference(locale, activity)); } } use(UserDictionaryListPreferenceController.class).setLocale(locale); } /** * Create a single User Dictionary Preference object, with its parameters set. * * @param locale The locale for which this user dictionary is for. * @return The corresponding preference. */ protected Preference createUserDictionaryPreference(String locale, Activity activity) { final Preference newPref = new Preference(getPrefContext()); final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION); if (null == locale) { newPref.setTitle(Locale.getDefault().getDisplayName()); } else { if ("".equals(locale)) { newPref.setTitle(getString(R.string.user_dict_settings_all_languages)); } else { newPref.setTitle(Utils.createLocaleFromString(locale).getDisplayName()); } intent.putExtra("locale", locale); newPref.getExtras().putString("locale", locale); } newPref.setIntent(intent); newPref.setFragment(UserDictionarySettings.class.getName()); return newPref; @Override protected int getPreferenceScreenResId() { return R.xml.user_dictionary_list_fragment; } @Override public void onResume() { super.onResume(); createUserDictSettings(getPreferenceScreen()); protected String getLogTag() { return TAG; } } src/com/android/settings/inputmethod/UserDictionaryListPreferenceController.java 0 → 100644 +211 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.inputmethod; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.provider.UserDictionary; import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import java.util.List; import java.util.Locale; import java.util.TreeSet; public class UserDictionaryListPreferenceController extends BasePreferenceController implements LifecycleObserver, OnStart { public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION = "android.settings.USER_DICTIONARY_SETTINGS"; private final String KEY_ALL_LANGUAGE = "all_languages"; private String mLocale; private PreferenceScreen mScreen; public UserDictionaryListPreferenceController(Context context, String key) { super(context, key); } public void setLocale(String locale) { mLocale = locale; } @Override public int getAvailabilityStatus() { return AVAILABLE; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); // This is to make newly inserted languages being sorted alphabetically when updating // the existing preferenceScreen, and for "For all languages" to be always on the top. screen.setOrderingAsAdded(false); mScreen = screen; } @Override public void onStart() { createUserDictSettings(); } @NonNull public static TreeSet<String> getUserDictionaryLocalesSet(Context context) { final Cursor cursor = context.getContentResolver().query( UserDictionary.Words.CONTENT_URI, new String[] {UserDictionary.Words.LOCALE}, null, null, null); final TreeSet<String> localeSet = new TreeSet<>(); if (cursor == null) { // The user dictionary service is not present or disabled. Return empty set. return localeSet; } try { if (cursor.moveToFirst()) { final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE); do { final String locale = cursor.getString(columnIndex); localeSet.add(null != locale ? locale : ""); } while (cursor.moveToNext()); } } finally { cursor.close(); } // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { // // For ICS, we need to show "For all languages" in case that the keyboard locale // // is different from the system locale // localeSet.add(""); // } final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); final List<InputMethodInfo> imis = imm.getEnabledInputMethodList(); for (final InputMethodInfo imi : imis) { final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList( imi, true /* allowsImplicitlySelectedSubtypes */); for (InputMethodSubtype subtype : subtypes) { final String locale = subtype.getLocale(); if (!TextUtils.isEmpty(locale)) { localeSet.add(locale); } } } // We come here after we have collected locales from existing user dictionary entries and // enabled subtypes. If we already have the locale-without-country version of the system // locale, we don't add the system locale to avoid confusion even though it's technically // correct to add it. if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) { localeSet.add(Locale.getDefault().toString()); } return localeSet; } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) TreeSet<String> getUserDictLocalesSet(Context context) { return getUserDictionaryLocalesSet(context); } /** * Creates the entries that allow the user to go into the user dictionary for each locale. */ private void createUserDictSettings() { final TreeSet<String> localeSet = getUserDictLocalesSet(mContext); final int prefCount = mScreen.getPreferenceCount(); String prefKey; if (mLocale != null) { // If the caller explicitly specify empty string as a locale, we'll show "all languages" // in the list. localeSet.add(mLocale); } if (localeSet.size() > 1) { // Have an "All languages" entry in the languages list if there are two or more active // languages localeSet.add(""); } // Update the existing preferenceScreen according to the corresponding data set. if (prefCount > 0) { for (int i = prefCount - 1; i >= 0; i--) { prefKey = mScreen.getPreference(i).getKey(); if (KEY_ALL_LANGUAGE.equals(prefKey)) { prefKey = ""; } if (!localeSet.isEmpty() && localeSet.contains(prefKey)) { localeSet.remove(prefKey); continue; } mScreen.removePreference(mScreen.findPreference(prefKey)); } } if (localeSet.isEmpty() && prefCount == 0) { mScreen.addPreference(createUserDictionaryPreference(null)); } else { for (String locale : localeSet) { mScreen.addPreference(createUserDictionaryPreference(locale)); } } } /** * Create a single User Dictionary Preference object, with its parameters set. * * @param locale The locale for which this user dictionary is for. * @return The corresponding preference. */ private Preference createUserDictionaryPreference(String locale) { final String KEY_LOCALE = "locale"; final Preference newPref = new Preference(mScreen.getContext()); final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION); if (locale == null) { newPref.setTitle(Locale.getDefault().getDisplayName()); newPref.setKey(Locale.getDefault().toString()); } else { if (TextUtils.isEmpty(locale)) { newPref.setTitle(mContext.getString(R.string.user_dict_settings_all_languages)); newPref.setKey(KEY_ALL_LANGUAGE); newPref.setOrder(0); } else { newPref.setTitle(Utils.createLocaleFromString(locale).getDisplayName()); newPref.setKey(locale); } intent.putExtra(KEY_LOCALE, locale); newPref.getExtras().putString(KEY_LOCALE, locale); } newPref.setIntent(intent); newPref.setFragment(UserDictionarySettings.class.getName()); return newPref; } } Loading
res/xml/user_dictionary_list_fragment.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="user_dict_list" android:title="@string/user_dict_settings_title" settings:controller="com.android.settings.inputmethod.UserDictionaryListPreferenceController"> </PreferenceScreen>
src/com/android/settings/core/PreferenceControllerListHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ public class PreferenceControllerListHelper { List<Bundle> preferenceMetadata; try { preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId, MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER); MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER | MetadataFlag.FLAG_INCLUDE_PREF_SCREEN); } catch (IOException | XmlPullParserException e) { Log.e(TAG, "Failed to parse preference xml for getting controllers", e); return controllers; Loading
src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java +16 −10 Original line number Diff line number Diff line Loading @@ -172,6 +172,7 @@ public class UserDictionaryAddWordContents { + "=? AND " + UserDictionary.Words.LOCALE + "=?"; private static final String HAS_WORD_SELECTION_ALL_LOCALES = UserDictionary.Words.WORD + "=? AND " + UserDictionary.Words.LOCALE + " is null"; private boolean hasWord(final String word, final Context context) { final Cursor cursor; // mLocale == "" indicates this is an entry for all languages. Here, mLocale can't Loading @@ -196,6 +197,7 @@ public class UserDictionaryAddWordContents { public static class LocaleRenderer { private final String mLocaleString; private final String mDescription; // LocaleString may NOT be null. public LocaleRenderer(final Context context, final String localeString) { mLocaleString = localeString; Loading @@ -207,13 +209,16 @@ public class UserDictionaryAddWordContents { mDescription = Utils.createLocaleFromString(localeString).getDisplayName(); } } @Override public String toString() { return mDescription; } public String getLocaleString() { return mLocaleString; } // "More languages..." is null ; "All languages" is the empty string. public boolean isMoreLanguages() { return null == mLocaleString; Loading @@ -229,7 +234,8 @@ public class UserDictionaryAddWordContents { // Helper method to get the list of locales to display for this word public ArrayList<LocaleRenderer> getLocalesList(final Activity activity) { final TreeSet<String> locales = UserDictionaryList.getUserDictionaryLocalesSet(activity); final TreeSet<String> locales = UserDictionaryListPreferenceController.getUserDictionaryLocalesSet(activity); // Remove our locale if it's in, because we're always gonna put it at the top locales.remove(mLocale); // mLocale may not be null final String systemLocale = Locale.getDefault().toString(); Loading
src/com/android/settings/inputmethod/UserDictionaryList.java +11 −139 Original line number Diff line number Diff line Loading @@ -16,33 +16,17 @@ package com.android.settings.inputmethod; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.provider.UserDictionary; import android.support.annotation.NonNull; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; import android.text.TextUtils; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; import com.android.settings.dashboard.DashboardFragment; import java.util.List; import java.util.Locale; import java.util.TreeSet; public class UserDictionaryList extends DashboardFragment { public class UserDictionaryList extends SettingsPreferenceFragment { public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION = "android.settings.USER_DICTIONARY_SETTINGS"; private String mLocale; private static final String TAG = "UserDictionaryList"; @Override public int getMetricsCategory() { Loading @@ -50,15 +34,8 @@ public class UserDictionaryList extends SettingsPreferenceFragment { } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity())); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getActivity().getActionBar().setTitle(R.string.user_dict_settings_title); public void onAttach(Context context) { super.onAttach(context); final Intent intent = getActivity().getIntent(); final String localeFromIntent = Loading @@ -76,122 +53,17 @@ public class UserDictionaryList extends SettingsPreferenceFragment { } else { locale = null; } mLocale = locale; } @NonNull public static TreeSet<String> getUserDictionaryLocalesSet(Context context) { final Cursor cursor = context.getContentResolver().query( UserDictionary.Words.CONTENT_URI, new String[]{UserDictionary.Words.LOCALE}, null, null, null); final TreeSet<String> localeSet = new TreeSet<>(); if (cursor == null) { // The user dictionary service is not present or disabled. Return empty set. return localeSet; } try { if (cursor.moveToFirst()) { final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE); do { final String locale = cursor.getString(columnIndex); localeSet.add(null != locale ? locale : ""); } while (cursor.moveToNext()); } } finally { cursor.close(); } // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { // // For ICS, we need to show "For all languages" in case that the keyboard locale // // is different from the system locale // localeSet.add(""); // } final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); final List<InputMethodInfo> imis = imm.getEnabledInputMethodList(); for (final InputMethodInfo imi : imis) { final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList( imi, true /* allowsImplicitlySelectedSubtypes */); for (InputMethodSubtype subtype : subtypes) { final String locale = subtype.getLocale(); if (!TextUtils.isEmpty(locale)) { localeSet.add(locale); } } } // We come here after we have collected locales from existing user dictionary entries and // enabled subtypes. If we already have the locale-without-country version of the system // locale, we don't add the system locale to avoid confusion even though it's technically // correct to add it. if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) { localeSet.add(Locale.getDefault().toString()); } return localeSet; } /** * Creates the entries that allow the user to go into the user dictionary for each locale. * * @param userDictGroup The group to put the settings in. */ protected void createUserDictSettings(PreferenceGroup userDictGroup) { final Activity activity = getActivity(); userDictGroup.removeAll(); final TreeSet<String> localeSet = UserDictionaryList.getUserDictionaryLocalesSet(activity); if (mLocale != null) { // If the caller explicitly specify empty string as a locale, we'll show "all languages" // in the list. localeSet.add(mLocale); } if (localeSet.size() > 1) { // Have an "All languages" entry in the languages list if there are two or more active // languages localeSet.add(""); } if (localeSet.isEmpty()) { userDictGroup.addPreference(createUserDictionaryPreference(null, activity)); } else { for (String locale : localeSet) { userDictGroup.addPreference(createUserDictionaryPreference(locale, activity)); } } use(UserDictionaryListPreferenceController.class).setLocale(locale); } /** * Create a single User Dictionary Preference object, with its parameters set. * * @param locale The locale for which this user dictionary is for. * @return The corresponding preference. */ protected Preference createUserDictionaryPreference(String locale, Activity activity) { final Preference newPref = new Preference(getPrefContext()); final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION); if (null == locale) { newPref.setTitle(Locale.getDefault().getDisplayName()); } else { if ("".equals(locale)) { newPref.setTitle(getString(R.string.user_dict_settings_all_languages)); } else { newPref.setTitle(Utils.createLocaleFromString(locale).getDisplayName()); } intent.putExtra("locale", locale); newPref.getExtras().putString("locale", locale); } newPref.setIntent(intent); newPref.setFragment(UserDictionarySettings.class.getName()); return newPref; @Override protected int getPreferenceScreenResId() { return R.xml.user_dictionary_list_fragment; } @Override public void onResume() { super.onResume(); createUserDictSettings(getPreferenceScreen()); protected String getLogTag() { return TAG; } }
src/com/android/settings/inputmethod/UserDictionaryListPreferenceController.java 0 → 100644 +211 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.inputmethod; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.provider.UserDictionary; import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import java.util.List; import java.util.Locale; import java.util.TreeSet; public class UserDictionaryListPreferenceController extends BasePreferenceController implements LifecycleObserver, OnStart { public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION = "android.settings.USER_DICTIONARY_SETTINGS"; private final String KEY_ALL_LANGUAGE = "all_languages"; private String mLocale; private PreferenceScreen mScreen; public UserDictionaryListPreferenceController(Context context, String key) { super(context, key); } public void setLocale(String locale) { mLocale = locale; } @Override public int getAvailabilityStatus() { return AVAILABLE; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); // This is to make newly inserted languages being sorted alphabetically when updating // the existing preferenceScreen, and for "For all languages" to be always on the top. screen.setOrderingAsAdded(false); mScreen = screen; } @Override public void onStart() { createUserDictSettings(); } @NonNull public static TreeSet<String> getUserDictionaryLocalesSet(Context context) { final Cursor cursor = context.getContentResolver().query( UserDictionary.Words.CONTENT_URI, new String[] {UserDictionary.Words.LOCALE}, null, null, null); final TreeSet<String> localeSet = new TreeSet<>(); if (cursor == null) { // The user dictionary service is not present or disabled. Return empty set. return localeSet; } try { if (cursor.moveToFirst()) { final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE); do { final String locale = cursor.getString(columnIndex); localeSet.add(null != locale ? locale : ""); } while (cursor.moveToNext()); } } finally { cursor.close(); } // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { // // For ICS, we need to show "For all languages" in case that the keyboard locale // // is different from the system locale // localeSet.add(""); // } final InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); final List<InputMethodInfo> imis = imm.getEnabledInputMethodList(); for (final InputMethodInfo imi : imis) { final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList( imi, true /* allowsImplicitlySelectedSubtypes */); for (InputMethodSubtype subtype : subtypes) { final String locale = subtype.getLocale(); if (!TextUtils.isEmpty(locale)) { localeSet.add(locale); } } } // We come here after we have collected locales from existing user dictionary entries and // enabled subtypes. If we already have the locale-without-country version of the system // locale, we don't add the system locale to avoid confusion even though it's technically // correct to add it. if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) { localeSet.add(Locale.getDefault().toString()); } return localeSet; } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) TreeSet<String> getUserDictLocalesSet(Context context) { return getUserDictionaryLocalesSet(context); } /** * Creates the entries that allow the user to go into the user dictionary for each locale. */ private void createUserDictSettings() { final TreeSet<String> localeSet = getUserDictLocalesSet(mContext); final int prefCount = mScreen.getPreferenceCount(); String prefKey; if (mLocale != null) { // If the caller explicitly specify empty string as a locale, we'll show "all languages" // in the list. localeSet.add(mLocale); } if (localeSet.size() > 1) { // Have an "All languages" entry in the languages list if there are two or more active // languages localeSet.add(""); } // Update the existing preferenceScreen according to the corresponding data set. if (prefCount > 0) { for (int i = prefCount - 1; i >= 0; i--) { prefKey = mScreen.getPreference(i).getKey(); if (KEY_ALL_LANGUAGE.equals(prefKey)) { prefKey = ""; } if (!localeSet.isEmpty() && localeSet.contains(prefKey)) { localeSet.remove(prefKey); continue; } mScreen.removePreference(mScreen.findPreference(prefKey)); } } if (localeSet.isEmpty() && prefCount == 0) { mScreen.addPreference(createUserDictionaryPreference(null)); } else { for (String locale : localeSet) { mScreen.addPreference(createUserDictionaryPreference(locale)); } } } /** * Create a single User Dictionary Preference object, with its parameters set. * * @param locale The locale for which this user dictionary is for. * @return The corresponding preference. */ private Preference createUserDictionaryPreference(String locale) { final String KEY_LOCALE = "locale"; final Preference newPref = new Preference(mScreen.getContext()); final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION); if (locale == null) { newPref.setTitle(Locale.getDefault().getDisplayName()); newPref.setKey(Locale.getDefault().toString()); } else { if (TextUtils.isEmpty(locale)) { newPref.setTitle(mContext.getString(R.string.user_dict_settings_all_languages)); newPref.setKey(KEY_ALL_LANGUAGE); newPref.setOrder(0); } else { newPref.setTitle(Utils.createLocaleFromString(locale).getDisplayName()); newPref.setKey(locale); } intent.putExtra(KEY_LOCALE, locale); newPref.getExtras().putString(KEY_LOCALE, locale); } newPref.setIntent(intent); newPref.setFragment(UserDictionarySettings.class.getName()); return newPref; } }