Implement new UI for IME settings

Bug: 4645160

Change-Id: If9046e7e96732f6ee4c0594cc66622b6462bdec9
This commit is contained in:
satok
2011-06-27 23:44:01 +09:00
parent 29865fed4d
commit 3fa13775e8
9 changed files with 561 additions and 340 deletions

View File

@@ -356,6 +356,7 @@
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<action android:name="com.android.settings.VOICE_INPUT_OUTPUT_SETTINGS" /> <action android:name="com.android.settings.VOICE_INPUT_OUTPUT_SETTINGS" />
<action android:name="android.settings.INPUT_METHOD_SETTINGS" />
<category android:name="android.intent.category.VOICE_LAUNCH" /> <category android:name="android.intent.category.VOICE_LAUNCH" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.settings.SHORTCUT" /> <category android:name="com.android.settings.SHORTCUT" />
@@ -391,23 +392,6 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="Settings$InputMethodConfigActivity"
android:theme="@android:style/Theme.Holo"
android:label="@string/configure_input_method"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.INPUT_METHOD_SETTINGS" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.inputmethod.InputMethodConfig" />
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
android:resource="@id/language_settings" />
</activity>
<activity android:name="Settings$UserDictionarySettingsActivity" <activity android:name="Settings$UserDictionarySettingsActivity"
android:theme="@android:style/Theme.Holo" android:theme="@android:style/Theme.Holo"
android:label="@string/user_dict_settings_titlebar" android:label="@string/user_dict_settings_titlebar"

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical">
<LinearLayout
android:id="@+id/inputmethod_pref"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground">
<LinearLayout
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="10dip"
android:gravity="center_vertical"
android:orientation="vertical" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dip"
android:layout_marginRight="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<TextView
android:id="@+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignLeft="@android:id/title"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="13sp"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="4" />
</RelativeLayout>
</LinearLayout>
<View
android:layout_width="2dip"
android:layout_height="match_parent"
android:layout_marginTop="5dip"
android:layout_marginBottom="5dip"
android:background="@android:drawable/divider_horizontal_dark" />
<ImageView
android:id="@+id/inputmethod_settings"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingLeft="15dip"
android:paddingRight="?android:attr/scrollbarSize"
android:src="@drawable/ic_sysbar_quicksettings"
android:layout_gravity="center"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<CheckBox
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:focusable="false"
android:clickable="false"/>

View File

@@ -150,4 +150,9 @@
<item name="android:layout_width">match_parent</item> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
</style> </style>
<style name="InputMethodPreferenceStyle">
<item name="android:layout">@layout/preference_inputmethod</item>
<item name="android:widgetLayout">@layout/preference_inputmethod_widget</item>
</style>
</resources> </resources>

View File

@@ -32,6 +32,35 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:key="keyboard_settings_category"
android:title="@string/keyboard_settings_category">
<PreferenceScreen android:key="current_input_method"
android:title="@string/current_input_method" />
</PreferenceCategory>
<PreferenceCategory
android:key="hard_keyboard"
android:title="@string/builtin_keyboard_settings_title"
android:persistent="false">
<CheckBoxPreference
android:key="auto_replace"
android:title="@string/auto_replace"
android:summaryOn="@string/auto_replace_summary"
android:summaryOff="@string/auto_replace_summary"
android:persistent="false"/>
<CheckBoxPreference
android:key="auto_caps"
android:title="@string/auto_caps"
android:summaryOn="@string/auto_caps_summary"
android:summaryOff="@string/auto_caps_summary"
android:persistent="false"/>
<CheckBoxPreference
android:key="auto_punctuate"
android:title="@string/auto_punctuate"
android:summaryOn="@string/auto_punctuate_summary"
android:summaryOff="@string/auto_punctuate_summary"
android:persistent="false"/>
</PreferenceCategory>
<PreferenceCategory android:key="voice_input_category" <PreferenceCategory android:key="voice_input_category"
android:title="@string/voice_input_category" > android:title="@string/voice_input_category" >
@@ -54,24 +83,6 @@
android:title="@string/tts_settings_title" /> android:title="@string/tts_settings_title" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:key="keyboard_settings_category"
android:title="@string/keyboard_settings_category">
<PreferenceScreen android:key="current_input_method"
android:title="@string/current_input_method" />
<ListPreference android:key="input_method_selector"
android:title="@string/input_method_selector"
android:persistent="true"
android:entryValues="@array/input_method_selector_values"
android:entries="@array/input_method_selector_titles"
android:defaultValue="@string/input_method_selector_visibility_default_value"/>
<PreferenceScreen android:key="configure_input_method"
android:title="@string/configure_input_method">
<intent android:action="android.settings.INPUT_METHOD_SETTINGS"/>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:key="pointer_settings_category" <PreferenceCategory android:key="pointer_settings_category"
android:title="@string/pointer_settings_category"> android:title="@string/pointer_settings_category">
<com.android.settings.PointerSpeedPreference <com.android.settings.PointerSpeedPreference

View File

@@ -544,7 +544,6 @@ public class Settings extends PreferenceActivity implements ButtonBarHandler {
public static class StorageSettingsActivity extends Settings { /* empty */ } public static class StorageSettingsActivity extends Settings { /* empty */ }
public static class WifiSettingsActivity extends Settings { /* empty */ } public static class WifiSettingsActivity extends Settings { /* empty */ }
public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ } public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
public static class InputMethodConfigActivity extends Settings { /* empty */ }
public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ } public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
public static class LocalePickerActivity extends Settings { /* empty */ } public static class LocalePickerActivity extends Settings { /* empty */ }
public static class UserDictionarySettingsActivity extends Settings { /* empty */ } public static class UserDictionarySettingsActivity extends Settings { /* empty */ }

View File

@@ -24,14 +24,25 @@ import com.android.settings.VoiceInputOutputSettings;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.provider.Settings; import android.provider.Settings;
import android.provider.Settings.System;
import android.text.TextUtils;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set; import java.util.Set;
public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
@@ -40,13 +51,28 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
private static final String KEY_PHONE_LANGUAGE = "phone_language"; private static final String KEY_PHONE_LANGUAGE = "phone_language";
private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method"; private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method";
private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector"; private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector";
private static final String KEY_LANGUAGE_SETTINGS_CATEGORY = "language_settings_category";
private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings"; private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings";
// false: on ICS or later
private static final boolean SHOW_INPUT_METHOD_SWITCHER_SETTINGS = false;
private static final String[] sSystemSettingNames = {
System.TEXT_AUTO_REPLACE, System.TEXT_AUTO_CAPS, System.TEXT_AUTO_PUNCTUATE,
};
private static final String[] sHardKeyboardKeys = {
"auto_replace", "auto_caps", "auto_punctuate",
};
private int mDefaultInputMethodSelectorVisibility = 0; private int mDefaultInputMethodSelectorVisibility = 0;
private ListPreference mShowInputMethodSelectorPref; private ListPreference mShowInputMethodSelectorPref;
private Preference mLanguagePref; private Preference mLanguagePref;
private ArrayList<InputMethodPreference> mInputMethodPreferenceList =
new ArrayList<InputMethodPreference>();
private boolean mHaveHardKeyboard;
private PreferenceCategory mHardKeyboardCategory;
private InputMethodManager mImm;
private List<InputMethodInfo> mImis;
private boolean mIsOnlyImeSettings;
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
@@ -66,13 +92,26 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
} else { } else {
mLanguagePref = findPreference(KEY_PHONE_LANGUAGE); mLanguagePref = findPreference(KEY_PHONE_LANGUAGE);
} }
if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
mShowInputMethodSelectorPref = (ListPreference)findPreference( mShowInputMethodSelectorPref = (ListPreference)findPreference(
KEY_INPUT_METHOD_SELECTOR); KEY_INPUT_METHOD_SELECTOR);
mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this);
// TODO: Update current input method name on summary // TODO: Update current input method name on summary
updateInputMethodSelectorSummary(loadInputMethodSelectorVisibility()); updateInputMethodSelectorSummary(loadInputMethodSelectorVisibility());
}
new VoiceInputOutputSettings(this).onCreate(); new VoiceInputOutputSettings(this).onCreate();
// Hard keyboard
final Configuration config = getResources().getConfiguration();
mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
// IME
mIsOnlyImeSettings = Settings.ACTION_INPUT_METHOD_SETTINGS.equals(
getActivity().getIntent().getAction());
mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
mImis = mImm.getInputMethodList();
createImePreferenceHierarchy((PreferenceGroup)findPreference("keyboard_settings_category"));
} }
private void updateInputMethodSelectorSummary(int value) { private void updateInputMethodSelectorSummary(int value) {
@@ -109,6 +148,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (!mIsOnlyImeSettings) {
if (mLanguagePref != null) { if (mLanguagePref != null) {
Configuration conf = getResources().getConfiguration(); Configuration conf = getResources().getConfiguration();
String locale = conf.locale.getDisplayName(conf.locale); String locale = conf.locale.getDisplayName(conf.locale);
@@ -119,14 +159,36 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
} }
updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS)); updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS));
if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this);
} }
}
// Hard keyboard
if (mHaveHardKeyboard) {
for (int i = 0; i < sHardKeyboardKeys.length; ++i) {
InputMethodPreference chkPref = (InputMethodPreference)
mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]);
chkPref.setChecked(
System.getInt(getContentResolver(), sSystemSettingNames[i], 1) > 0);
}
}
// IME
InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
this, getContentResolver(), mImis, null);
updateActiveInputMethodsSummary();
}
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
mShowInputMethodSelectorPref.setOnPreferenceChangeListener(null); mShowInputMethodSelectorPref.setOnPreferenceChangeListener(null);
} }
InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
this, getContentResolver(), mImis, mHaveHardKeyboard);
}
@Override @Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
@@ -142,6 +204,17 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
getSystemService(Context.INPUT_METHOD_SERVICE); getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showInputMethodPicker(); imm.showInputMethodPicker();
} }
} else if (preference instanceof CheckBoxPreference) {
final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
if (mHaveHardKeyboard) {
for (int i = 0; i < sHardKeyboardKeys.length; ++i) {
if (chkPref == mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i])) {
System.putInt(getContentResolver(), sSystemSettingNames[i],
chkPref.isChecked() ? 1 : 0);
return true;
}
}
}
} }
return super.onPreferenceTreeClick(preferenceScreen, preference); return super.onPreferenceTreeClick(preferenceScreen, preference);
} }
@@ -164,12 +237,84 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
@Override @Override
public boolean onPreferenceChange(Preference preference, Object value) { public boolean onPreferenceChange(Preference preference, Object value) {
if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
if (preference == mShowInputMethodSelectorPref) { if (preference == mShowInputMethodSelectorPref) {
if (value instanceof String) { if (value instanceof String) {
saveInputMethodSelectorVisibility((String)value); saveInputMethodSelectorVisibility((String)value);
} }
} }
}
return false; return false;
} }
private void updateActiveInputMethodsSummary() {
for (Preference pref : mInputMethodPreferenceList) {
if (pref instanceof InputMethodPreference) {
((InputMethodPreference)pref).updateSummary();
}
}
}
private InputMethodPreference getInputMethodPreference(InputMethodInfo imi, int imiSize) {
final PackageManager pm = getPackageManager();
final CharSequence label = imi.loadLabel(pm);
// IME settings
final Intent intent;
final String settingsActivity = imi.getSettingsActivity();
if (!TextUtils.isEmpty(settingsActivity)) {
intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(imi.getPackageName(), settingsActivity);
} else {
intent = null;
}
// Add a check box for enabling/disabling IME
InputMethodPreference pref = new InputMethodPreference(this, intent, mImm, imi, imiSize);
pref.setKey(imi.getId());
pref.setTitle(label);
return pref;
}
private void createImePreferenceHierarchy(PreferenceGroup root) {
final Preference hardKeyPref = findPreference("hard_keyboard");
if (mIsOnlyImeSettings) {
getPreferenceScreen().removeAll();
if (hardKeyPref != null && mHaveHardKeyboard) {
getPreferenceScreen().addPreference(hardKeyPref);
}
if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
getPreferenceScreen().addPreference(mShowInputMethodSelectorPref);
}
getPreferenceScreen().addPreference(root);
}
if (hardKeyPref != null) {
if (mHaveHardKeyboard) {
mHardKeyboardCategory = (PreferenceCategory) hardKeyPref;
} else {
getPreferenceScreen().removePreference(hardKeyPref);
}
}
root.removeAll();
mInputMethodPreferenceList.clear();
if (!mIsOnlyImeSettings) {
// Current IME selection
final PreferenceScreen currentIme = new PreferenceScreen(getActivity(), null);
currentIme.setKey(KEY_CURRENT_INPUT_METHOD);
currentIme.setTitle(getResources().getString(R.string.current_input_method));
root.addPreference(currentIme);
}
final int N = (mImis == null ? 0 : mImis.size());
for (int i = 0; i < N; ++i) {
final InputMethodInfo imi = mImis.get(i);
final InputMethodPreference pref = getInputMethodPreference(imi, N);
mInputMethodPreferenceList.add(pref);
}
Collections.sort(mInputMethodPreferenceList);
for (int i = 0; i < N; ++i) {
root.addPreference(mInputMethodPreferenceList.get(i));
}
}
} }

View File

@@ -1,286 +0,0 @@
/*
* Copyright (C) 2010 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 com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.provider.Settings.System;
import android.text.TextUtils;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class InputMethodConfig extends SettingsPreferenceFragment {
private static final String[] sSystemSettingNames = {
System.TEXT_AUTO_REPLACE, System.TEXT_AUTO_CAPS, System.TEXT_AUTO_PUNCTUATE,
};
private static final String[] sHardKeyboardKeys = {
"auto_replace", "auto_caps", "auto_punctuate",
};
private AlertDialog mDialog = null;
private boolean mHaveHardKeyboard;
private PreferenceCategory mHardKeyboardCategory;
// Map of imi and its preferences
final private HashMap<String, List<Preference>> mInputMethodPrefsMap =
new HashMap<String, List<Preference>>();
final private HashMap<InputMethodInfo, Preference> mActiveInputMethodsPrefMap =
new HashMap<InputMethodInfo, Preference>();
private List<InputMethodInfo> mInputMethodProperties;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Configuration config = getResources().getConfiguration();
mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
InputMethodManager imm = (InputMethodManager) getSystemService(
Context.INPUT_METHOD_SERVICE);
// TODO: Change mInputMethodProperties to Map
mInputMethodProperties = imm.getInputMethodList();
setPreferenceScreen(createPreferenceHierarchy());
}
@Override
public void onResume() {
super.onResume();
ContentResolver resolver = getContentResolver();
if (mHaveHardKeyboard) {
for (int i = 0; i < sHardKeyboardKeys.length; ++i) {
CheckBoxPreference chkPref = (CheckBoxPreference)
mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]);
chkPref.setChecked(System.getInt(resolver, sSystemSettingNames[i], 1) > 0);
}
}
InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
this, resolver, mInputMethodProperties, mInputMethodPrefsMap);
updateActiveInputMethodsSummary();
}
@Override
public void onPause() {
super.onPause();
InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
mInputMethodProperties, mHaveHardKeyboard);
}
private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref,
final String imiId) {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
mDialog = (new AlertDialog.Builder(getActivity()))
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setCancelable(true)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
chkPref.setChecked(true);
for (Preference pref: mInputMethodPrefsMap.get(imiId)) {
pref.setEnabled(true);
}
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.create();
mDialog.setMessage(getResources().getString(R.string.ime_security_warning,
imi.getServiceInfo().applicationInfo.loadLabel(getPackageManager())));
mDialog.show();
}
private InputMethodInfo getInputMethodInfoFromImiId(String imiId) {
final int N = mInputMethodProperties.size();
for (int i = 0; i < N; ++i) {
InputMethodInfo imi = mInputMethodProperties.get(i);
if (imiId.equals(imi.getId())) {
return imi;
}
}
return null;
}
@Override
public boolean onPreferenceTreeClick(
PreferenceScreen preferenceScreen, Preference preference) {
if (preference instanceof CheckBoxPreference) {
final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
if (mHaveHardKeyboard) {
for (int i = 0; i < sHardKeyboardKeys.length; ++i) {
if (chkPref == mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i])) {
System.putInt(getContentResolver(), sSystemSettingNames[i],
chkPref.isChecked() ? 1 : 0);
return true;
}
}
}
final String imiId = chkPref.getKey();
if (chkPref.isChecked()) {
InputMethodInfo selImi = getInputMethodInfoFromImiId(imiId);
if (selImi != null) {
if (InputMethodAndSubtypeUtil.isSystemIme(selImi)) {
// This is a built-in IME, so no need to warn.
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
} else {
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
chkPref.setChecked(false);
showSecurityWarnDialog(selImi, chkPref, imiId);
} else {
for (Preference pref: mInputMethodPrefsMap.get(imiId)) {
pref.setEnabled(false);
}
}
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
}
private void addInputMethodPreference(PreferenceScreen root, InputMethodInfo imi,
final int imiSize) {
PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(getActivity());
root.addPreference(keyboardSettingsCategory);
final String imiId = imi.getId();
mInputMethodPrefsMap.put(imiId, new ArrayList<Preference>());
PackageManager pm = getPackageManager();
CharSequence label = imi.loadLabel(pm);
keyboardSettingsCategory.setTitle(label);
final boolean isSystemIME = InputMethodAndSubtypeUtil.isSystemIme(imi);
// Add a check box for enabling/disabling IME
CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity());
chkbxPref.setKey(imiId);
chkbxPref.setTitle(label);
keyboardSettingsCategory.addPreference(chkbxPref);
// Disable the toggle if it's the only keyboard in the system, or it's a system IME.
if (imiSize <= 1 || isSystemIME) {
chkbxPref.setEnabled(false);
}
Intent intent;
// Add subtype settings when this IME has two or more subtypes.
PreferenceScreen prefScreen = new PreferenceScreen(getActivity(), null);
prefScreen.setTitle(R.string.active_input_method_subtypes);
if (imi.getSubtypeCount() > 1) {
prefScreen.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference){
final Bundle bundle = new Bundle();
bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
startFragment(InputMethodConfig.this,
InputMethodAndSubtypeEnabler.class.getName(),
0, bundle);
return true;
}
});
keyboardSettingsCategory.addPreference(prefScreen);
mActiveInputMethodsPrefMap.put(imi, prefScreen);
mInputMethodPrefsMap.get(imiId).add(prefScreen);
}
// Add IME settings
String settingsActivity = imi.getSettingsActivity();
if (!TextUtils.isEmpty(settingsActivity)) {
prefScreen = new PreferenceScreen(getActivity(), null);
prefScreen.setTitle(R.string.input_method_settings);
intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(imi.getPackageName(), settingsActivity);
prefScreen.setIntent(intent);
keyboardSettingsCategory.addPreference(prefScreen);
mInputMethodPrefsMap.get(imiId).add(prefScreen);
}
}
private PreferenceScreen createPreferenceHierarchy() {
addPreferencesFromResource(R.xml.hard_keyboard_settings);
PreferenceScreen root = getPreferenceScreen();
if (mHaveHardKeyboard) {
mHardKeyboardCategory = (PreferenceCategory) findPreference("hard_keyboard");
} else {
root.removeAll();
}
final int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size());
for (int i = 0; i < N; ++i) {
addInputMethodPreference(root, mInputMethodProperties.get(i), N);
}
return root;
}
private void updateActiveInputMethodsSummary() {
final InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
for (InputMethodInfo imi: mActiveInputMethodsPrefMap.keySet()) {
Preference pref = mActiveInputMethodsPrefMap.get(imi);
List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi, true);
StringBuilder summary = new StringBuilder();
boolean subtypeAdded = false;
for (InputMethodSubtype subtype: subtypes) {
if (subtypeAdded) {
summary.append(", ");
}
final CharSequence subtypeLabel = subtype.getDisplayName(getActivity(),
imi.getPackageName(), imi.getServiceInfo().applicationInfo);
summary.append(subtypeLabel);
subtypeAdded = true;
}
pref.setSummary(summary.toString());
}
}
}

View File

@@ -0,0 +1,254 @@
/*
* Copyright (C) 2011 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 com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.PreferenceActivity;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Comparator;
import java.util.List;
public class InputMethodPreference extends CheckBoxPreference
implements Comparator<InputMethodPreference> {
private static final String TAG = InputMethodPreference.class.getSimpleName();
private static final float DISABLED_ALPHA = 0.4f;
private final SettingsPreferenceFragment mFragment;
private final InputMethodInfo mImi;
private final InputMethodManager mImm;
private final Intent mSettingsIntent;
private final boolean mIsSystemIme;
private AlertDialog mDialog = null;
private ImageView mInputMethodSettingsButton;
private TextView mTitleText;
private TextView mSummaryText;
private View mInputMethodPref;
public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent,
InputMethodManager imm, InputMethodInfo imi, int imiCount) {
super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle);
setLayoutResource(R.layout.preference_inputmethod);
setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
mFragment = fragment;
mSettingsIntent = settingsIntent;
mImm = imm;
mImi = imi;
updateSummary();
mIsSystemIme = InputMethodAndSubtypeUtil.isSystemIme(imi);
final int subtypeCount = imi.getSubtypeCount();
boolean onlyAux = true;
if (subtypeCount == 0) {
onlyAux = false;
} else {
for (int i = 0; i < subtypeCount; ++i) {
final InputMethodSubtype subtype = imi.getSubtypeAt(i);
if (!subtype.isAuxiliary()) {
onlyAux = false;
break;
}
}
}
if (imiCount <= 1 || (mIsSystemIme && !onlyAux)) {
setEnabled(false);
}
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
mInputMethodPref = view.findViewById(R.id.inputmethod_pref);
mInputMethodPref.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View arg0) {
if (isChecked()) {
setChecked(false);
} else {
if (mIsSystemIme) {
setChecked(true);
} else {
showSecurityWarnDialog(mImi, InputMethodPreference.this);
}
}
}
});
mInputMethodSettingsButton = (ImageView)view.findViewById(R.id.inputmethod_settings);
mTitleText = (TextView)view.findViewById(android.R.id.title);
mSummaryText = (TextView)view.findViewById(android.R.id.summary);
if (mSettingsIntent != null) {
mInputMethodSettingsButton.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View arg0) {
mFragment.startActivity(mSettingsIntent);
}
});
}
final boolean hasSubtypes = mImi.getSubtypeCount() > 1;
final String imiId = mImi.getId();
if (hasSubtypes) {
final OnLongClickListener listener = new OnLongClickListener() {
@Override
public boolean onLongClick(View arg0) {
final Bundle bundle = new Bundle();
bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
0, bundle);
return true;
}
};
mInputMethodSettingsButton.setOnLongClickListener(listener);
}
if (mSettingsIntent == null) {
mInputMethodSettingsButton.setVisibility(View.GONE);
} else {
enableSettingsButton();
}
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
enableSettingsButton();
}
private void enableSettingsButton() {
if (mInputMethodSettingsButton != null) {
final boolean checked = isChecked();
mInputMethodSettingsButton.setEnabled(checked);
mInputMethodSettingsButton.setClickable(checked);
mInputMethodSettingsButton.setFocusable(checked);
if (!checked) {
mInputMethodSettingsButton.setAlpha(DISABLED_ALPHA);
}
}
if (mTitleText != null) {
mTitleText.setEnabled(true);
}
if (mSummaryText != null) {
mSummaryText.setEnabled(true);
}
}
public static boolean startFragment(
Fragment fragment, String fragmentClass, int requestCode, Bundle extras) {
if (fragment.getActivity() instanceof PreferenceActivity) {
PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity();
preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment,
requestCode);
return true;
} else {
Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
+ "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
+ ")");
return false;
}
}
public String getSummaryString() {
final StringBuilder builder = new StringBuilder();
final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true);
for (InputMethodSubtype subtype : subtypes) {
if (builder.length() > 0) {
builder.append(", ");
}
final CharSequence subtypeLabel = subtype.getDisplayName(mFragment.getActivity(),
mImi.getPackageName(), mImi.getServiceInfo().applicationInfo);
builder.append(subtypeLabel);
}
return builder.toString();
}
public void updateSummary() {
final String summary = getSummaryString();
if (TextUtils.isEmpty(summary)) {
return;
}
setSummary(summary);
}
@Override
public void setChecked(boolean checked) {
super.setChecked(checked);
saveImeSettings();
}
private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref) {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
mDialog = (new AlertDialog.Builder(mFragment.getActivity()))
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setCancelable(true)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
chkPref.setChecked(true);
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create();
mDialog.setMessage(mFragment.getResources().getString(R.string.ime_security_warning,
imi.getServiceInfo().applicationInfo.loadLabel(
mFragment.getActivity().getPackageManager())));
mDialog.show();
}
@Override
public int compare(InputMethodPreference arg0, InputMethodPreference arg1) {
if (arg0.isEnabled() == arg0.isEnabled()) {
return arg0.mImi.getId().compareTo(arg1.mImi.getId());
} else {
// Prefer system IMEs
return arg0.isEnabled() ? 1 : -1;
}
}
private void saveImeSettings() {
InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
mFragment, mFragment.getActivity().getContentResolver(), mImm.getInputMethodList(),
mFragment.getResources().getConfiguration().keyboard
== Configuration.KEYBOARD_QWERTY);
}
}