From 766b286187d02b3da6e0142376a4478072f30a16 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Fri, 18 May 2012 15:04:45 -0700 Subject: [PATCH] Add UI to select multiple keyboard layouts. Bug: 6405203 Change-Id: I27ca4630aebcb39b83298d37d8fb3f4ef0080317 --- AndroidManifest.xml | 2 +- res/layout/keyboard_layout_dialog_switch_hint.xml | 37 +++ res/values/strings.xml | 16 +- .../InputMethodAndLanguageSettings.java | 48 ++- .../inputmethod/KeyboardLayoutDialogFragment.java | 354 +++++++++++++++++++++ .../settings/inputmethod/KeyboardLayoutPicker.java | 154 --------- .../inputmethod/KeyboardLayoutPickerFragment.java | 154 +++++++++ 7 files changed, 597 insertions(+), 168 deletions(-) create mode 100644 res/layout/keyboard_layout_dialog_switch_hint.xml create mode 100644 src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java delete mode 100644 src/com/android/settings/inputmethod/KeyboardLayoutPicker.java create mode 100644 src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 3cf1520d30..8386c3a29f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -433,7 +433,7 @@ + android:value="com.android.settings.inputmethod.KeyboardLayoutPickerFragment" /> diff --git a/res/layout/keyboard_layout_dialog_switch_hint.xml b/res/layout/keyboard_layout_dialog_switch_hint.xml new file mode 100644 index 0000000000..336d543d18 --- /dev/null +++ b/res/layout/keyboard_layout_dialog_switch_hint.xml @@ -0,0 +1,37 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 3c46b48636..543c659e3c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2659,14 +2659,20 @@ Redirect vibrator to game controller when connected. - - - Choose keyboard layout - - No keyboard layouts are available. + + + Choose keyboard layout + + Set up keyboard layouts + + (Switch with ctrl-space) Default + + + Keyboard layouts + User dictionary diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java index 8c341c624b..d848503885 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java +++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java @@ -52,7 +52,8 @@ import java.util.List; import java.util.TreeSet; public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment - implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener { + implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener, + KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener { private static final String KEY_PHONE_LANGUAGE = "phone_language"; private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method"; @@ -86,6 +87,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment private Handler mHandler; @SuppressWarnings("unused") private SettingsObserver mSettingsObserver; + private Intent mIntentWaitingForResult; @Override public void onCreate(Bundle icicle) { @@ -409,15 +411,10 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment && device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { final String inputDeviceDescriptor = device.getDescriptor(); final String keyboardLayoutDescriptor = - mIm.getKeyboardLayoutForInputDevice(inputDeviceDescriptor); + mIm.getCurrentKeyboardLayoutForInputDevice(inputDeviceDescriptor); final KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ? mIm.getKeyboardLayout(keyboardLayoutDescriptor) : null; - final Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setClass(getActivity(), KeyboardLayoutPickerActivity.class); - intent.putExtra(KeyboardLayoutPicker.EXTRA_INPUT_DEVICE_DESCRIPTOR, - inputDeviceDescriptor); - final PreferenceScreen pref = new PreferenceScreen(getActivity(), null); pref.setTitle(device.getName()); if (keyboardLayout != null) { @@ -425,7 +422,13 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment } else { pref.setSummary(R.string.keyboard_layout_default_label); } - pref.setIntent(intent); + pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + showKeyboardLayoutDialog(inputDeviceDescriptor); + return true; + } + }); mHardKeyboardPreferenceList.add(pref); } } @@ -453,6 +456,35 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment } } + private void showKeyboardLayoutDialog(String inputDeviceDescriptor) { + KeyboardLayoutDialogFragment fragment = + new KeyboardLayoutDialogFragment(inputDeviceDescriptor); + fragment.setTargetFragment(this, 0); + fragment.show(getActivity().getFragmentManager(), "keyboardLayout"); + } + + @Override + public void onSetupKeyboardLayouts(String inputDeviceDescriptor) { + final Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setClass(getActivity(), KeyboardLayoutPickerActivity.class); + intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_DESCRIPTOR, + inputDeviceDescriptor); + mIntentWaitingForResult = intent; + startActivityForResult(intent, 0); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (mIntentWaitingForResult != null) { + String inputDeviceDescriptor = mIntentWaitingForResult.getStringExtra( + KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_DESCRIPTOR); + mIntentWaitingForResult = null; + showKeyboardLayoutDialog(inputDeviceDescriptor); + } + } + private void updateGameControllers() { if (haveInputDeviceWithVibrator()) { getPreferenceScreen().addPreference(mGameControllerCategory); diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java new file mode 100644 index 0000000000..a232a0f70a --- /dev/null +++ b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2012 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.Settings.KeyboardLayoutPickerActivity; + +import android.app.AlertDialog; +import android.app.Activity; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.LoaderManager.LoaderCallbacks; +import android.content.AsyncTaskLoader; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.Loader; +import android.content.res.Resources; +import android.hardware.input.InputManager; +import android.hardware.input.KeyboardLayout; +import android.hardware.input.InputManager.InputDeviceListener; +import android.os.Bundle; +import android.view.InputDevice; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckedTextView; +import android.widget.RadioButton; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Collections; + +public class KeyboardLayoutDialogFragment extends DialogFragment + implements InputDeviceListener, LoaderCallbacks { + private static final String KEY_INPUT_DEVICE_DESCRIPTOR = "inputDeviceDescriptor"; + + private String mInputDeviceDescriptor; + private int mInputDeviceId = -1; + private InputManager mIm; + private KeyboardLayoutAdapter mAdapter; + + public KeyboardLayoutDialogFragment() { + } + + public KeyboardLayoutDialogFragment(String inputDeviceDescriptor) { + mInputDeviceDescriptor = inputDeviceDescriptor; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + Context context = activity.getBaseContext(); + mIm = (InputManager)context.getSystemService(Context.INPUT_SERVICE); + mAdapter = new KeyboardLayoutAdapter(context); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + mInputDeviceDescriptor = savedInstanceState.getString(KEY_INPUT_DEVICE_DESCRIPTOR); + } + + getLoaderManager().initLoader(0, null, this); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(KEY_INPUT_DEVICE_DESCRIPTOR, mInputDeviceDescriptor); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Context context = getActivity(); + LayoutInflater inflater = LayoutInflater.from(context); + AlertDialog.Builder builder = new AlertDialog.Builder(context) + .setTitle(R.string.keyboard_layout_dialog_title) + .setPositiveButton(R.string.keyboard_layout_dialog_setup_button, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onSetupLayoutsButtonClicked(); + } + }) + .setSingleChoiceItems(mAdapter, -1, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onKeyboardLayoutClicked(which); + } + }) + .setView(inflater.inflate(R.layout.keyboard_layout_dialog_switch_hint, null)); + updateSwitchHintVisibility(); + return builder.create(); + } + + @Override + public void onResume() { + super.onResume(); + + mIm.registerInputDeviceListener(this, null); + + InputDevice inputDevice = mIm.getInputDeviceByDescriptor(mInputDeviceDescriptor); + if (inputDevice == null) { + dismiss(); + return; + } + mInputDeviceId = inputDevice.getId(); + } + + @Override + public void onPause() { + mIm.unregisterInputDeviceListener(this); + mInputDeviceId = -1; + + super.onPause(); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + dismiss(); + } + + private void onSetupLayoutsButtonClicked() { + ((OnSetupKeyboardLayoutsListener)getTargetFragment()).onSetupKeyboardLayouts( + mInputDeviceDescriptor); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + show(getActivity().getFragmentManager(), "layout"); + } + + private void onKeyboardLayoutClicked(int which) { + if (which >= 0 && which < mAdapter.getCount()) { + KeyboardLayout keyboardLayout = mAdapter.getItem(which); + if (keyboardLayout != null) { + mIm.setCurrentKeyboardLayoutForInputDevice(mInputDeviceDescriptor, + keyboardLayout.getDescriptor()); + } + dismiss(); + } + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new KeyboardLayoutLoader(getActivity().getBaseContext(), mInputDeviceDescriptor); + } + + @Override + public void onLoadFinished(Loader loader, Keyboards data) { + mAdapter.clear(); + mAdapter.addAll(data.keyboardLayouts); + mAdapter.setCheckedItem(data.current); + AlertDialog dialog = (AlertDialog)getDialog(); + if (dialog != null) { + dialog.getListView().setItemChecked(data.current, true); + } + updateSwitchHintVisibility(); + } + + @Override + public void onLoaderReset(Loader loader) { + mAdapter.clear(); + updateSwitchHintVisibility(); + } + + @Override + public void onInputDeviceAdded(int deviceId) { + } + + @Override + public void onInputDeviceChanged(int deviceId) { + if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) { + getLoaderManager().restartLoader(0, null, this); + } + } + + @Override + public void onInputDeviceRemoved(int deviceId) { + if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) { + dismiss(); + } + } + + private void updateSwitchHintVisibility() { + AlertDialog dialog = (AlertDialog)getDialog(); + if (dialog != null) { + View customPanel = dialog.findViewById(com.android.internal.R.id.customPanel); + customPanel.setVisibility(mAdapter.getCount() > 1 ? View.VISIBLE : View.GONE); + } + } + + private static final class KeyboardLayoutAdapter extends ArrayAdapter { + private final LayoutInflater mInflater; + private int mCheckedItem = -1; + + public KeyboardLayoutAdapter(Context context) { + super(context, com.android.internal.R.layout.simple_list_item_2_single_choice); + mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + public void setCheckedItem(int position) { + mCheckedItem = position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + KeyboardLayout item = getItem(position); + String label, collection; + if (item != null) { + label = item.getLabel(); + collection = item.getCollection(); + } else { + label = getContext().getString(R.string.keyboard_layout_default_label); + collection = ""; + } + + boolean checked = (position == mCheckedItem); + if (collection.isEmpty()) { + return inflateOneLine(convertView, parent, label, checked); + } else { + return inflateTwoLine(convertView, parent, label, collection, checked); + } + } + + private View inflateOneLine(View convertView, ViewGroup parent, + String label, boolean checked) { + View view = convertView; + if (view == null || isTwoLine(view)) { + view = mInflater.inflate( + com.android.internal.R.layout.simple_list_item_single_choice, + parent, false); + setTwoLine(view, false); + } + CheckedTextView headline = (CheckedTextView) view.findViewById(android.R.id.text1); + headline.setText(label); + headline.setChecked(checked); + return view; + } + + private View inflateTwoLine(View convertView, ViewGroup parent, + String label, String collection, boolean checked) { + View view = convertView; + if (view == null || !isTwoLine(view)) { + view = mInflater.inflate( + com.android.internal.R.layout.simple_list_item_2_single_choice, + parent, false); + setTwoLine(view, true); + } + TextView headline = (TextView) view.findViewById(android.R.id.text1); + TextView subText = (TextView) view.findViewById(android.R.id.text2); + RadioButton radioButton = + (RadioButton)view.findViewById(com.android.internal.R.id.radio); + headline.setText(label); + subText.setText(collection); + radioButton.setChecked(checked); + return view; + } + + private static boolean isTwoLine(View view) { + return view.getTag() == Boolean.TRUE; + } + + private static void setTwoLine(View view, boolean twoLine) { + view.setTag(Boolean.valueOf(twoLine)); + } + } + + private static final class KeyboardLayoutLoader extends AsyncTaskLoader { + private final String mInputDeviceDescriptor; + + public KeyboardLayoutLoader(Context context, String inputDeviceDescriptor) { + super(context); + mInputDeviceDescriptor = inputDeviceDescriptor; + } + + @Override + public Keyboards loadInBackground() { + Keyboards keyboards = new Keyboards(); + InputManager im = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE); + String[] keyboardLayoutDescriptors = im.getKeyboardLayoutsForInputDevice( + mInputDeviceDescriptor); + for (String keyboardLayoutDescriptor : keyboardLayoutDescriptors) { + KeyboardLayout keyboardLayout = im.getKeyboardLayout(keyboardLayoutDescriptor); + if (keyboardLayout != null) { + keyboards.keyboardLayouts.add(keyboardLayout); + } + } + Collections.sort(keyboards.keyboardLayouts); + + String currentKeyboardLayoutDescriptor = + im.getCurrentKeyboardLayoutForInputDevice(mInputDeviceDescriptor); + if (currentKeyboardLayoutDescriptor != null) { + final int numKeyboardLayouts = keyboards.keyboardLayouts.size(); + for (int i = 0; i < numKeyboardLayouts; i++) { + if (keyboards.keyboardLayouts.get(i).getDescriptor().equals( + currentKeyboardLayoutDescriptor)) { + keyboards.current = i; + break; + } + } + } + + if (keyboards.keyboardLayouts.isEmpty()) { + keyboards.keyboardLayouts.add(null); // default layout + keyboards.current = 0; + } + return keyboards; + } + + @Override + protected void onStartLoading() { + super.onStartLoading(); + forceLoad(); + } + + @Override + protected void onStopLoading() { + super.onStopLoading(); + cancelLoad(); + } + } + + public static final class Keyboards { + public final ArrayList keyboardLayouts = new ArrayList(); + public int current = -1; + } + + public interface OnSetupKeyboardLayoutsListener { + public void onSetupKeyboardLayouts(String inputDeviceDescriptor); + } +} \ No newline at end of file diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPicker.java b/src/com/android/settings/inputmethod/KeyboardLayoutPicker.java deleted file mode 100644 index 6c341b82e2..0000000000 --- a/src/com/android/settings/inputmethod/KeyboardLayoutPicker.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2012 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 android.app.ListFragment; -import android.app.LoaderManager.LoaderCallbacks; -import android.content.AsyncTaskLoader; -import android.content.Context; -import android.content.Loader; -import android.hardware.input.InputManager; -import android.hardware.input.KeyboardLayout; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import android.widget.TextView; - -import java.util.Arrays; - -public class KeyboardLayoutPicker extends ListFragment - implements LoaderCallbacks { - private static final String TAG = "KeyboardLayoutPicker"; - - private String mInputDeviceDescriptor; - - /** - * Intent extra: The input device descriptor of the keyboard whose keyboard - * layout is to be changed. - */ - public static final String EXTRA_INPUT_DEVICE_DESCRIPTOR = "input_device_descriptor"; - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - mInputDeviceDescriptor = getActivity().getIntent().getStringExtra( - EXTRA_INPUT_DEVICE_DESCRIPTOR); - if (mInputDeviceDescriptor == null) { - Log.e(TAG, "Missing expected intent parameter: " + EXTRA_INPUT_DEVICE_DESCRIPTOR); - getActivity().finish(); - } - - setEmptyText(getActivity().getText(R.string.keyboard_layout_picker_empty_text)); - getLoaderManager().initLoader(0, null, this); - } - - @Override - public void onResume() { - super.onResume(); - getListView().requestFocus(); - } - - @Override - public void onListItemClick(ListView l, View v, int position, long id) { - if (mInputDeviceDescriptor != null) { - KeyboardLayout c = (KeyboardLayout)l.getItemAtPosition(position); - InputManager im = (InputManager)getActivity().getSystemService(Context.INPUT_SERVICE); - im.setKeyboardLayoutForInputDevice(mInputDeviceDescriptor, c.getDescriptor()); - } - - getActivity().finish(); - } - - @Override - public Loader onCreateLoader(int id, Bundle args) { - return new KeyboardLayoutLoader(getActivity()); - } - - @Override - public void onLoadFinished(Loader loader, - KeyboardLayout[] data) { - setListAdapter(new KeyboardLayoutAdapter(getActivity(), data)); - } - - @Override - public void onLoaderReset(Loader loader) { - setListAdapter(null); - } - - private static final class KeyboardLayoutAdapter - extends ArrayAdapter { - private LayoutInflater mInflater; - - public KeyboardLayoutAdapter(Context context, KeyboardLayout[] list) { - super(context, android.R.layout.simple_list_item_2, list); - mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View view = convertView; - if (view == null) { - view = mInflater.inflate(android.R.layout.simple_list_item_2, parent, false); - } - - KeyboardLayout item = getItem(position); - TextView headline = (TextView) view.findViewById(android.R.id.text1); - TextView subText = (TextView) view.findViewById(android.R.id.text2); - headline.setText(item.getLabel()); - subText.setText(item.getCollection()); - return view; - } - } - - private static final class KeyboardLayoutLoader - extends AsyncTaskLoader { - public KeyboardLayoutLoader(Context context) { - super(context); - } - - @Override - public KeyboardLayout[] loadInBackground() { - InputManager im = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE); - KeyboardLayout[] list = im.getKeyboardLayouts(); - KeyboardLayout[] listWithDefault = new KeyboardLayout[list.length + 1]; - listWithDefault[0] = new KeyboardLayout(null, - getContext().getString(R.string.keyboard_layout_default_label), ""); - System.arraycopy(list, 0, listWithDefault, 1, list.length); - Arrays.sort(listWithDefault); - return listWithDefault; - } - - @Override - protected void onStartLoading() { - super.onStartLoading(); - forceLoad(); - } - - @Override - protected void onStopLoading() { - super.onStopLoading(); - cancelLoad(); - } - } -} diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java new file mode 100644 index 0000000000..932dd10e1d --- /dev/null +++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2012 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.content.Context; +import android.hardware.input.InputManager; +import android.hardware.input.InputManager.InputDeviceListener; +import android.hardware.input.KeyboardLayout; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceScreen; +import android.view.InputDevice; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment + implements InputDeviceListener { + private String mInputDeviceDescriptor; + private int mInputDeviceId = -1; + private InputManager mIm; + private KeyboardLayout[] mKeyboardLayouts; + private HashMap mPreferenceMap = + new HashMap(); + + /** + * Intent extra: The input device descriptor of the keyboard whose keyboard + * layout is to be changed. + */ + public static final String EXTRA_INPUT_DEVICE_DESCRIPTOR = "input_device_descriptor"; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + mInputDeviceDescriptor = getActivity().getIntent().getStringExtra( + EXTRA_INPUT_DEVICE_DESCRIPTOR); + if (mInputDeviceDescriptor == null) { + getActivity().finish(); + } + + mIm = (InputManager)getSystemService(Context.INPUT_SERVICE); + mKeyboardLayouts = mIm.getKeyboardLayouts(); + Arrays.sort(mKeyboardLayouts); + setPreferenceScreen(createPreferenceHierarchy()); + } + + @Override + public void onResume() { + super.onResume(); + + mIm.registerInputDeviceListener(this, null); + + InputDevice inputDevice = mIm.getInputDeviceByDescriptor(mInputDeviceDescriptor); + if (inputDevice == null) { + getActivity().finish(); + return; + } + mInputDeviceId = inputDevice.getId(); + + updateCheckedState(); + } + + @Override + public void onPause() { + mIm.unregisterInputDeviceListener(this); + mInputDeviceId = -1; + + super.onPause(); + } + + @Override + public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, + Preference preference) { + if (preference instanceof CheckBoxPreference) { + CheckBoxPreference checkboxPref = (CheckBoxPreference)preference; + KeyboardLayout layout = mPreferenceMap.get(checkboxPref); + if (layout != null) { + boolean checked = checkboxPref.isChecked(); + if (checked) { + mIm.addKeyboardLayoutForInputDevice(mInputDeviceDescriptor, + layout.getDescriptor()); + } else { + mIm.removeKeyboardLayoutForInputDevice(mInputDeviceDescriptor, + layout.getDescriptor()); + } + return true; + } + } + return super.onPreferenceTreeClick(preferenceScreen, preference); + } + + @Override + public void onInputDeviceAdded(int deviceId) { + } + + @Override + public void onInputDeviceChanged(int deviceId) { + if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) { + updateCheckedState(); + } + } + + @Override + public void onInputDeviceRemoved(int deviceId) { + if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) { + getActivity().finish(); + } + } + + private PreferenceScreen createPreferenceHierarchy() { + PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity()); + Context context = getActivity(); + + for (KeyboardLayout layout : mKeyboardLayouts) { + CheckBoxPreference pref = new CheckBoxPreference(context); + pref.setTitle(layout.getLabel()); + pref.setSummary(layout.getCollection()); + root.addPreference(pref); + mPreferenceMap.put(pref, layout); + } + return root; + } + + private void updateCheckedState() { + String[] enabledKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice( + mInputDeviceDescriptor); + Arrays.sort(enabledKeyboardLayouts); + + for (Map.Entry entry : mPreferenceMap.entrySet()) { + entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts, + entry.getValue().getDescriptor()) >= 0); + } + } +} -- 2.11.0