diff --git a/samples/SoftKeyboard/res/drawable-hdpi/sym_keyboard_language_switch.png b/samples/SoftKeyboard/res/drawable-hdpi/sym_keyboard_language_switch.png new file mode 100644 index 000000000..78d3a1fc5 Binary files /dev/null and b/samples/SoftKeyboard/res/drawable-hdpi/sym_keyboard_language_switch.png differ diff --git a/samples/SoftKeyboard/res/drawable-mdpi/sym_keyboard_language_switch.png b/samples/SoftKeyboard/res/drawable-mdpi/sym_keyboard_language_switch.png new file mode 100644 index 000000000..828929bc8 Binary files /dev/null and b/samples/SoftKeyboard/res/drawable-mdpi/sym_keyboard_language_switch.png differ diff --git a/samples/SoftKeyboard/res/xml/method.xml b/samples/SoftKeyboard/res/xml/method.xml index 2f2d6f0a3..37a59c861 100644 --- a/samples/SoftKeyboard/res/xml/method.xml +++ b/samples/SoftKeyboard/res/xml/method.xml @@ -22,6 +22,7 @@ - + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + + - + android:keyWidth="15%p" android:keyEdgeFlags="left" /> + + + diff --git a/samples/SoftKeyboard/res/xml/symbols_shift.xml b/samples/SoftKeyboard/res/xml/symbols_shift.xml index d7139f340..fa551f29a 100755 --- a/samples/SoftKeyboard/res/xml/symbols_shift.xml +++ b/samples/SoftKeyboard/res/xml/symbols_shift.xml @@ -69,8 +69,14 @@ - + android:keyWidth="15%p" android:keyEdgeFlags="left" /> + + + diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java index 67787dca4..aae67cd1b 100644 --- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java +++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java @@ -22,11 +22,35 @@ import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.inputmethodservice.Keyboard; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; public class LatinKeyboard extends Keyboard { private Key mEnterKey; private Key mSpaceKey; + /** + * Stores the current state of the mode change key. Its width will be dynamically updated to + * match the region of {@link #mModeChangeKey} when {@link #mModeChangeKey} becomes invisible. + */ + private Key mModeChangeKey; + /** + * Stores the current state of the language switch key (a.k.a. globe key). This should be + * visible while {@link InputMethodManager#shouldOfferSwitchingToNextInputMethod(IBinder)} + * returns true. When this key becomes invisible, its width will be shrunk to zero. + */ + private Key mLanguageSwitchKey; + /** + * Stores the size and other information of {@link #mModeChangeKey} when + * {@link #mLanguageSwitchKey} is visible. This should be immutable and will be used only as a + * reference size when the visibility of {@link #mLanguageSwitchKey} is changed. + */ + private Key mSavedModeChangeKey; + /** + * Stores the size and other information of {@link #mLanguageSwitchKey} when it is visible. + * This should be immutable and will be used only as a reference size when the visibility of + * {@link #mLanguageSwitchKey} is changed. + */ + private Key mSavedLanguageSwitchKey; public LatinKeyboard(Context context, int xmlLayoutResId) { super(context, xmlLayoutResId); @@ -45,10 +69,39 @@ public class LatinKeyboard extends Keyboard { mEnterKey = key; } else if (key.codes[0] == ' ') { mSpaceKey = key; + } else if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) { + mModeChangeKey = key; + mSavedModeChangeKey = new LatinKey(res, parent, x, y, parser); + } else if (key.codes[0] == LatinKeyboardView.KEYCODE_LANGUAGE_SWITCH) { + mLanguageSwitchKey = key; + mSavedLanguageSwitchKey = new LatinKey(res, parent, x, y, parser); } return key; } - + + /** + * Dynamically change the visibility of the language switch key (a.k.a. globe key). + * @param visible True if the language switch key should be visible. + */ + void setLanguageSwitchKeyVisibility(boolean visible) { + if (visible) { + // The language switch key should be visible. Restore the size of the mode change key + // and language switch key using the saved layout. + mModeChangeKey.width = mSavedModeChangeKey.width; + mModeChangeKey.x = mSavedModeChangeKey.x; + mLanguageSwitchKey.width = mSavedLanguageSwitchKey.width; + mLanguageSwitchKey.icon = mSavedLanguageSwitchKey.icon; + mLanguageSwitchKey.iconPreview = mSavedLanguageSwitchKey.iconPreview; + } else { + // The language switch key should be hidden. Change the width of the mode change key + // to fill the space of the language key so that the user will not see any strange gap. + mModeChangeKey.width = mSavedModeChangeKey.width + mSavedLanguageSwitchKey.width; + mLanguageSwitchKey.width = 0; + mLanguageSwitchKey.icon = null; + mLanguageSwitchKey.iconPreview = null; + } + } + /** * This looks at the ime options given by the current editor, to set the * appropriate label on the keyboard's enter key (if it has one). @@ -57,7 +110,7 @@ public class LatinKeyboard extends Keyboard { if (mEnterKey == null) { return; } - + switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) { case EditorInfo.IME_ACTION_GO: mEnterKey.iconPreview = null; @@ -93,7 +146,8 @@ public class LatinKeyboard extends Keyboard { static class LatinKey extends Keyboard.Key { - public LatinKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) { + public LatinKey(Resources res, Keyboard.Row parent, int x, int y, + XmlResourceParser parser) { super(res, parent, x, y, parser); } diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java index 489c283fd..abfa2f21f 100644 --- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java +++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java @@ -26,6 +26,8 @@ import android.view.inputmethod.InputMethodSubtype; public class LatinKeyboardView extends KeyboardView { static final int KEYCODE_OPTIONS = -100; + // TODO: Move this into android.inputmethodservice.Keyboard + static final int KEYCODE_LANGUAGE_SWITCH = -101; public LatinKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java index 7c4a17e1f..cdebde5a7 100644 --- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java +++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java @@ -16,14 +16,17 @@ package com.example.android.softkeyboard; +import android.app.Dialog; import android.inputmethodservice.InputMethodService; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; +import android.os.IBinder; import android.text.InputType; import android.text.method.MetaKeyKeyListener; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.View; +import android.view.Window; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -114,10 +117,17 @@ public class SoftKeyboard extends InputMethodService mInputView = (LatinKeyboardView) getLayoutInflater().inflate( R.layout.input, null); mInputView.setOnKeyboardActionListener(this); - mInputView.setKeyboard(mQwertyKeyboard); + setLatinKeyboard(mQwertyKeyboard); return mInputView; } + private void setLatinKeyboard(LatinKeyboard nextKeyboard) { + final boolean shouldSupportLanguageSwitchKey = + mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken()); + nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey); + mInputView.setKeyboard(nextKeyboard); + } + /** * Called by the framework when your view for showing candidates needs to * be generated, like {@link #onCreateInputView}. @@ -247,7 +257,7 @@ public class SoftKeyboard extends InputMethodService @Override public void onStartInputView(EditorInfo attribute, boolean restarting) { super.onStartInputView(attribute, restarting); // Apply the selected keyboard to the input view. - mInputView.setKeyboard(mCurKeyboard); + setLatinKeyboard(mCurKeyboard); mInputView.closing(); final InputMethodSubtype subtype = mInputMethodManager.getCurrentInputMethodSubtype(); mInputView.setSubtypeOnSpaceKey(subtype); @@ -509,19 +519,19 @@ public class SoftKeyboard extends InputMethodService } else if (primaryCode == Keyboard.KEYCODE_CANCEL) { handleClose(); return; + } else if (primaryCode == LatinKeyboardView.KEYCODE_LANGUAGE_SWITCH) { + handleLanguageSwitch(); + return; } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) { // Show a menu or somethin' } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE && mInputView != null) { Keyboard current = mInputView.getKeyboard(); if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) { - current = mQwertyKeyboard; + setLatinKeyboard(mQwertyKeyboard); } else { - current = mSymbolsKeyboard; - } - mInputView.setKeyboard(current); - if (current == mSymbolsKeyboard) { - current.setShifted(false); + setLatinKeyboard(mSymbolsKeyboard); + mSymbolsKeyboard.setShifted(false); } } else { handleCharacter(primaryCode, keyCodes); @@ -597,11 +607,11 @@ public class SoftKeyboard extends InputMethodService mInputView.setShifted(mCapsLock || !mInputView.isShifted()); } else if (currentKeyboard == mSymbolsKeyboard) { mSymbolsKeyboard.setShifted(true); - mInputView.setKeyboard(mSymbolsShiftedKeyboard); + setLatinKeyboard(mSymbolsShiftedKeyboard); mSymbolsShiftedKeyboard.setShifted(true); } else if (currentKeyboard == mSymbolsShiftedKeyboard) { mSymbolsShiftedKeyboard.setShifted(false); - mInputView.setKeyboard(mSymbolsKeyboard); + setLatinKeyboard(mSymbolsKeyboard); mSymbolsKeyboard.setShifted(false); } } @@ -629,6 +639,22 @@ public class SoftKeyboard extends InputMethodService mInputView.closing(); } + private IBinder getToken() { + final Dialog dialog = getWindow(); + if (dialog == null) { + return null; + } + final Window window = dialog.getWindow(); + if (window == null) { + return null; + } + return window.getAttributes().token; + } + + private void handleLanguageSwitch() { + mInputMethodManager.switchToNextInputMethod(getToken(), false /* onlyCurrentIme */); + } + private void checkToggleCapsLock() { long now = System.currentTimeMillis(); if (mLastShiftTime + 800 > now) {