From bfcd98edc7c5ac28fdc1e4b7a97b2912124e622a Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 23 Jul 2014 17:08:18 -0700 Subject: [PATCH] Use fragment for input preference screen This CL introduces a common abstract class, SunScreenFragment, for PreferenceFragment that implements a PreferenceScreen of the main settings preference screen. Bug: 16522808 Change-Id: I11fba71b5e9f96208b261e0c0314de8a41720d0f --- java/res/xml/prefs.xml | 36 +----- java/res/xml/prefs_screen_input.xml | 53 ++++++++ .../latin/settings/InputSettingsFragment.java | 100 +++++++++++++++ .../latin/settings/SettingsActivity.java | 3 +- .../latin/settings/SettingsFragment.java | 20 --- .../latin/settings/SubScreenFragment.java | 118 ++++++++++++++++++ .../latin/utils/FragmentUtils.java | 2 + 7 files changed, 276 insertions(+), 56 deletions(-) create mode 100644 java/res/xml/prefs_screen_input.xml create mode 100644 java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java create mode 100644 java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index 7e4c28496..749551c2a 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -19,41 +19,9 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" android:key="english_ime_settings"> - - - - - - - + android:key="screen_input" /> + + + + + + + + + + diff --git a/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java new file mode 100644 index 000000000..f459d68dd --- /dev/null +++ b/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.settings; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.os.Bundle; +import android.preference.Preference; + +import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.SubtypeSwitcher; + +/** + * "Input preferences" settings sub screen. + * + * This settings sub screen handles the following input preferences. + * - Auto-capitalization + * - Double-space period + * - Vibrate on keypress + * - Sound on keypress + * - Popup on keypress + * - Voice input key + */ +public final class InputSettingsFragment extends SubScreenFragment { + @Override + public void onCreate(final Bundle icicle) { + super.onCreate(icicle); + addPreferencesFromResource(R.xml.prefs_screen_input); + + final Resources res = getResources(); + final Context context = getActivity(); + + // When we are called from the Settings application but we are not already running, some + // singleton and utility classes may not have been initialized. We have to call + // initialization method of these classes here. See {@link LatinIME#onCreate()}. + SubtypeSwitcher.init(context); + + final boolean showVoiceKeyOption = res.getBoolean( + R.bool.config_enable_show_voice_key_option); + if (!showVoiceKeyOption) { + removePreference(Settings.PREF_VOICE_INPUT_KEY); + } + if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) { + removePreference(Settings.PREF_VIBRATE_ON); + } + if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) { + removePreference(Settings.PREF_POPUP_ON); + } + + refreshEnablingsOfKeypressSoundAndVibrationSettings(); + } + + @Override + public void onResume() { + super.onResume(); + final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY); + if (voiceInputKeyOption != null) { + final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance() + .isShortcutImeEnabled(); + voiceInputKeyOption.setEnabled(isShortcutImeEnabled); + voiceInputKeyOption.setSummary( + isShortcutImeEnabled ? null : getText(R.string.voice_input_disabled_summary)); + } + } + + @Override + public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { + final Resources res = getResources(); + if (key.equals(Settings.PREF_POPUP_ON)) { + setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, + Settings.readKeyPreviewPopupEnabled(prefs, res)); + } + refreshEnablingsOfKeypressSoundAndVibrationSettings(); + } + + private void refreshEnablingsOfKeypressSoundAndVibrationSettings() { + final SharedPreferences prefs = getSharedPreferences(); + final Resources res = getResources(); + setPreferenceEnabled(Settings.PREF_VIBRATION_DURATION_SETTINGS, + Settings.readVibrationEnabled(prefs, res)); + setPreferenceEnabled(Settings.PREF_KEYPRESS_SOUND_VOLUME, + Settings.readKeypressSoundEnabled(prefs, res)); + } +} diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java index c899507e3..c7b9dcdd9 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java @@ -35,8 +35,7 @@ public final class SettingsActivity extends PreferenceActivity { return intent; } - // TODO: Uncomment the override annotation once we start using SDK version 19. - // @Override + @Override public boolean isValidFragment(String fragmentName) { return FragmentUtils.isValidFragment(fragmentName); } diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java index b289174c6..ec842eff2 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java @@ -42,7 +42,6 @@ import com.android.inputmethod.dictionarypack.DictionarySettingsActivity; import com.android.inputmethod.keyboard.KeyboardTheme; import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.define.ProductionFlags; import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager; import com.android.inputmethod.latin.userdictionary.UserDictionaryList; @@ -114,7 +113,6 @@ public final class SettingsFragment extends InputMethodSettingsFragment // When we are called from the Settings application but we are not already running, some // singleton and utility classes may not have been initialized. We have to call // initialization method of these classes here. See {@link LatinIME#onCreate()}. - SubtypeSwitcher.init(context); SubtypeLocaleUtils.init(context); AudioAndHapticFeedbackManager.init(context); @@ -123,8 +121,6 @@ public final class SettingsFragment extends InputMethodSettingsFragment ensureConsistencyOfAutoCorrectionSettings(); - final PreferenceScreen inputScreen = - (PreferenceScreen) findPreference(Settings.SCREEN_INPUT); final PreferenceScreen multiLingualScreen = (PreferenceScreen) findPreference(Settings.SCREEN_MULTI_LINGUAL); final PreferenceScreen gestureScreen = @@ -140,14 +136,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment advancedScreen.removePreference(debugScreen); } - final boolean showVoiceKeyOption = res.getBoolean( - R.bool.config_enable_show_voice_key_option); - if (!showVoiceKeyOption) { - removePreference(Settings.PREF_VOICE_INPUT_KEY, inputScreen); - } - if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) { - removePreference(Settings.PREF_VIBRATE_ON, inputScreen); removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedScreen); } if (!Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS) { @@ -158,7 +147,6 @@ public final class SettingsFragment extends InputMethodSettingsFragment // TODO: consolidate key preview dismiss delay with the key preview animation parameters. if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) { - removePreference(Settings.PREF_POPUP_ON, inputScreen); removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedScreen); } else { // TODO: Cleanup this setup. @@ -234,14 +222,6 @@ public final class SettingsFragment extends InputMethodSettingsFragment super.onResume(); final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); final Resources res = getResources(); - final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY); - if (voiceInputKeyOption != null) { - final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance() - .isShortcutImeEnabled(); - voiceInputKeyOption.setEnabled(isShortcutImeEnabled); - voiceInputKeyOption.setSummary(isShortcutImeEnabled ? null - : res.getText(R.string.voice_input_disabled_summary)); - } final TwoStatePreference showSetupWizardIcon = (TwoStatePreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON); if (showSetupWizardIcon != null) { diff --git a/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java new file mode 100644 index 000000000..c70bf2997 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.settings; + +import android.app.backup.BackupManager; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.util.Log; + +/** + * A base abstract class for a {@link PreferenceFragment} that implements a nested + * {@link PreferenceScreen} of the main preference screen. + */ +abstract class SubScreenFragment extends PreferenceFragment + implements OnSharedPreferenceChangeListener { + private OnSharedPreferenceChangeListener mSharedPreferenceChangeListener; + + static void setPreferenceEnabled(final String prefKey, final boolean enabled, + final PreferenceScreen screen) { + final Preference preference = screen.findPreference(prefKey); + if (preference != null) { + preference.setEnabled(enabled); + } + } + + static void removePreference(final String prefKey, final PreferenceScreen screen) { + final Preference preference = screen.findPreference(prefKey); + if (preference != null) { + screen.removePreference(preference); + } + } + + static void updateListPreferenceSummaryToCurrentValue(final String prefKey, + final PreferenceScreen screen) { + // Because the "%s" summary trick of {@link ListPreference} doesn't work properly before + // KitKat, we need to update the summary programmatically. + final ListPreference listPreference = (ListPreference)screen.findPreference(prefKey); + if (listPreference == null) { + return; + } + final CharSequence entries[] = listPreference.getEntries(); + final int entryIndex = listPreference.findIndexOfValue(listPreference.getValue()); + listPreference.setSummary(entryIndex < 0 ? null : entries[entryIndex]); + } + + final void setPreferenceEnabled(final String prefKey, final boolean enabled) { + setPreferenceEnabled(prefKey, enabled, getPreferenceScreen()); + } + + final void removePreference(final String prefKey) { + removePreference(prefKey, getPreferenceScreen()); + } + + final void updateListPreferenceSummaryToCurrentValue(final String prefKey) { + updateListPreferenceSummaryToCurrentValue(prefKey, getPreferenceScreen()); + } + + final SharedPreferences getSharedPreferences() { + return getPreferenceManager().getSharedPreferences(); + } + + @Override + public void addPreferencesFromResource(final int preferencesResId) { + super.addPreferencesFromResource(preferencesResId); + TwoStatePreferenceHelper.replaceCheckBoxPreferencesBySwitchPreferences( + getPreferenceScreen()); + } + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mSharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { + final SubScreenFragment fragment = SubScreenFragment.this; + final Context context = fragment.getActivity(); + if (context == null || fragment.getPreferenceScreen() == null) { + final String tag = fragment.getClass().getSimpleName(); + // TODO: Introduce a static function to register this class and ensure that + // onCreate must be called before "onSharedPreferenceChanged" is called. + Log.w(tag, "onSharedPreferenceChanged called before activity starts."); + return; + } + new BackupManager(context).dataChanged(); + fragment.onSharedPreferenceChanged(prefs, key); + } + }; + getSharedPreferences().registerOnSharedPreferenceChangeListener( + mSharedPreferenceChangeListener); + } + + @Override + public void onDestroy() { + getSharedPreferences().unregisterOnSharedPreferenceChangeListener( + mSharedPreferenceChangeListener); + super.onDestroy(); + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java index e300bd1d3..5d77097b2 100644 --- a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java @@ -20,6 +20,7 @@ import com.android.inputmethod.dictionarypack.DictionarySettingsFragment; import com.android.inputmethod.latin.about.AboutPreferences; import com.android.inputmethod.latin.settings.AdditionalSubtypeSettings; import com.android.inputmethod.latin.settings.DebugSettings; +import com.android.inputmethod.latin.settings.InputSettingsFragment; import com.android.inputmethod.latin.settings.SettingsFragment; import com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment; import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordFragment; @@ -34,6 +35,7 @@ public class FragmentUtils { static { sLatinImeFragments.add(DictionarySettingsFragment.class.getName()); sLatinImeFragments.add(AboutPreferences.class.getName()); + sLatinImeFragments.add(InputSettingsFragment.class.getName()); sLatinImeFragments.add(AdditionalSubtypeSettings.class.getName()); sLatinImeFragments.add(DebugSettings.class.getName()); sLatinImeFragments.add(SettingsFragment.class.getName());