Reload keyboard after SoftInputWindow size changed

Bug: 4450008
Change-Id: Ic6c457db808d8e7479bfaa509192c07a384453e2
main
Tadashi G. Takaoka 2011-05-17 19:02:32 +09:00
parent a205d23ffd
commit e896d31bb9
10 changed files with 97 additions and 59 deletions

View File

@ -151,16 +151,11 @@ public class Keyboard {
* @param context the application or service context * @param context the application or service context
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys. * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
* @param id keyboard identifier * @param id keyboard identifier
* @param width keyboard width
*/ */
public Keyboard(Context context, int xmlLayoutResId, KeyboardId id) {
this(context, xmlLayoutResId, id,
context.getResources().getDisplayMetrics().widthPixels,
context.getResources().getDisplayMetrics().heightPixels);
}
private Keyboard(Context context, int xmlLayoutResId, KeyboardId id, int width, public Keyboard(Context context, int xmlLayoutResId, KeyboardId id, int width) {
int height) { final Resources res = context.getResources();
Resources res = context.getResources();
GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
GRID_SIZE = GRID_WIDTH * GRID_HEIGHT; GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
@ -168,7 +163,8 @@ public class Keyboard {
final int horizontalEdgesPadding = (int)res.getDimension( final int horizontalEdgesPadding = (int)res.getDimension(
R.dimen.keyboard_horizontal_edges_padding); R.dimen.keyboard_horizontal_edges_padding);
mDisplayWidth = width - horizontalEdgesPadding * 2; mDisplayWidth = width - horizontalEdgesPadding * 2;
mDisplayHeight = height; // TODO: Adjust the height by referring to the height of area available for drawing as well.
mDisplayHeight = res.getDisplayMetrics().heightPixels;
mDefaultHorizontalGap = 0; mDefaultHorizontalGap = 0;
setKeyWidth(mDisplayWidth / 10); setKeyWidth(mDisplayWidth / 10);

View File

@ -40,6 +40,7 @@ public class KeyboardId {
public final Locale mLocale; public final Locale mLocale;
public final int mOrientation; public final int mOrientation;
public final int mWidth;
public final int mMode; public final int mMode;
public final int mXmlId; public final int mXmlId;
public final int mColorScheme; public final int mColorScheme;
@ -49,17 +50,20 @@ public class KeyboardId {
public final boolean mHasVoiceKey; public final boolean mHasVoiceKey;
public final int mImeAction; public final int mImeAction;
public final boolean mEnableShiftLock; public final boolean mEnableShiftLock;
public final String mXmlName; public final String mXmlName;
public final EditorInfo mAttribute;
private final int mHashCode; private final int mHashCode;
public KeyboardId(String xmlName, int xmlId, int colorScheme, Locale locale, int orientation, public KeyboardId(String xmlName, int xmlId, int colorScheme, Locale locale, int orientation,
int mode, EditorInfo attribute, boolean hasSettingsKey, boolean voiceKeyEnabled, int width, int mode, EditorInfo attribute, boolean hasSettingsKey,
boolean hasVoiceKey, boolean enableShiftLock) { boolean voiceKeyEnabled, boolean hasVoiceKey, boolean enableShiftLock) {
final int inputType = (attribute != null) ? attribute.inputType : 0; final int inputType = (attribute != null) ? attribute.inputType : 0;
final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
this.mLocale = locale; this.mLocale = locale;
this.mOrientation = orientation; this.mOrientation = orientation;
this.mWidth = width;
this.mMode = mode; this.mMode = mode;
this.mXmlId = xmlId; this.mXmlId = xmlId;
this.mColorScheme = colorScheme; this.mColorScheme = colorScheme;
@ -73,11 +77,14 @@ public class KeyboardId {
this.mImeAction = imeOptions & ( this.mImeAction = imeOptions & (
EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION); EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
this.mEnableShiftLock = enableShiftLock; this.mEnableShiftLock = enableShiftLock;
this.mXmlName = xmlName; this.mXmlName = xmlName;
this.mAttribute = attribute;
this.mHashCode = Arrays.hashCode(new Object[] { this.mHashCode = Arrays.hashCode(new Object[] {
locale, locale,
orientation, orientation,
width,
mode, mode,
xmlId, xmlId,
colorScheme, colorScheme,
@ -90,6 +97,18 @@ public class KeyboardId {
}); });
} }
public KeyboardId cloneWithNewLayout(String xmlName, int xmlId) {
return new KeyboardId(xmlName, xmlId, mColorScheme, mLocale, mOrientation, mWidth, mMode,
mAttribute, mHasSettingsKey, mVoiceKeyEnabled, mHasVoiceKey, mEnableShiftLock);
}
public KeyboardId cloneWithNewGeometry(int width) {
if (mWidth == width)
return this;
return new KeyboardId(mXmlName, mXmlId, mColorScheme, mLocale, mOrientation, width, mMode,
mAttribute, mHasSettingsKey, mVoiceKeyEnabled, mHasVoiceKey, mEnableShiftLock);
}
public int getXmlId() { public int getXmlId() {
return mXmlId; return mXmlId;
} }
@ -118,6 +137,7 @@ public class KeyboardId {
boolean equals(KeyboardId other) { boolean equals(KeyboardId other) {
return other.mLocale.equals(this.mLocale) return other.mLocale.equals(this.mLocale)
&& other.mOrientation == this.mOrientation && other.mOrientation == this.mOrientation
&& other.mWidth == this.mWidth
&& other.mMode == this.mMode && other.mMode == this.mMode
&& other.mXmlId == this.mXmlId && other.mXmlId == this.mXmlId
&& other.mColorScheme == this.mColorScheme && other.mColorScheme == this.mColorScheme
@ -136,10 +156,10 @@ public class KeyboardId {
@Override @Override
public String toString() { public String toString() {
return String.format("[%s.xml %s %s %s imeAction=%s %s%s%s%s%s%s]", return String.format("[%s.xml %s %s%d %s %s %s%s%s%s%s%s]",
mXmlName, mXmlName,
mLocale, mLocale,
(mOrientation == 1 ? "port" : "land"), (mOrientation == 1 ? "port" : "land"), mWidth,
modeName(mMode), modeName(mMode),
EditorInfoCompatUtils.imeOptionsName(mImeAction), EditorInfoCompatUtils.imeOptionsName(mImeAction),
(mPasswordInput ? " passwordInput" : ""), (mPasswordInput ? " passwordInput" : ""),

View File

@ -37,7 +37,7 @@ import java.util.Locale;
public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "KeyboardSwitcher"; private static final String TAG = "KeyboardSwitcher";
private static final boolean DEBUG = false; private static final boolean DEBUG_CACHE = false;
public static final boolean DEBUG_STATE = false; public static final boolean DEBUG_STATE = false;
private static String sConfigDefaultKeyboardThemeId; private static String sConfigDefaultKeyboardThemeId;
@ -99,6 +99,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO;
private int mLayoutId; private int mLayoutId;
private int mKeyboardWidth;
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
@ -151,17 +152,39 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// Update the settings key state because number of enabled IMEs could have been changed // Update the settings key state because number of enabled IMEs could have been changed
mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService); mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService);
final KeyboardId id = getKeyboardId(attribute, isSymbols); final KeyboardId id = getKeyboardId(attribute, isSymbols);
makeSymbolsKeyboardIds(id.mMode, attribute);
mCurrentId = id; // Note: This comment is only applied for phone number keyboard layout.
final Resources res = mInputMethodService.getResources(); // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch
mInputView.setKeyPreviewPopupEnabled(Settings.Values.isKeyPreviewPopupEnabled(mPrefs, res), // between "phone keyboard" and "phone symbols keyboard". But on xlarge device,
Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, res)); // "@integer/key_shift" key code is used for that purpose in order to properly display
// "more" and "locked more" key labels. To achieve these behavior, we should initialize
// mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
// respectively here for xlarge device's layout switching.
mSymbolsId = makeSiblingKeyboardId(id, R.xml.kbd_symbols, R.xml.kbd_phone);
mSymbolsShiftedId = makeSiblingKeyboardId(
id, R.xml.kbd_symbols_shift, R.xml.kbd_phone_symbols);
setKeyboard(getKeyboard(id)); setKeyboard(getKeyboard(id));
} }
public void onSizeChanged() {
final int width = mInputMethodService.getWindow().getWindow().getDecorView().getWidth();
if (width == 0)
return;
mKeyboardWidth = width;
// Set keyboard with new width.
final KeyboardId newId = mCurrentId.cloneWithNewGeometry(width);
setKeyboard(getKeyboard(newId));
}
private void setKeyboard(final Keyboard newKeyboard) { private void setKeyboard(final Keyboard newKeyboard) {
final Keyboard oldKeyboard = mInputView.getKeyboard(); final Keyboard oldKeyboard = mInputView.getKeyboard();
mInputView.setKeyboard(newKeyboard); mInputView.setKeyboard(newKeyboard);
mCurrentId = newKeyboard.mId;
final Resources res = mInputMethodService.getResources();
mInputView.setKeyPreviewPopupEnabled(
Settings.Values.isKeyPreviewPopupEnabled(mPrefs, res),
Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, res));
final boolean localeChanged = (oldKeyboard == null) final boolean localeChanged = (oldKeyboard == null)
|| !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); || !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
@ -175,19 +198,19 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final Locale savedLocale = Utils.setSystemLocale(res, final Locale savedLocale = Utils.setSystemLocale(res,
mSubtypeSwitcher.getInputLocale()); mSubtypeSwitcher.getInputLocale());
keyboard = new LatinKeyboard(mInputMethodService, id); keyboard = new LatinKeyboard(mInputMethodService, id, id.mWidth);
if (id.mEnableShiftLock) { if (id.mEnableShiftLock) {
keyboard.enableShiftLock(); keyboard.enableShiftLock();
} }
mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard)); mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard));
if (DEBUG) if (DEBUG_CACHE)
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
+ ((ref == null) ? "LOAD" : "GCed") + " id=" + id); + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
Utils.setSystemLocale(res, savedLocale); Utils.setSystemLocale(res, savedLocale);
} else if (DEBUG) { } else if (DEBUG_CACHE) {
Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id); Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id);
} }
@ -244,33 +267,19 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final boolean hasSettingsKey = hasSettingsKey(attribute); final boolean hasSettingsKey = hasSettingsKey(attribute);
final Resources res = mInputMethodService.getResources(); final Resources res = mInputMethodService.getResources();
final int orientation = res.getConfiguration().orientation; final int orientation = res.getConfiguration().orientation;
if (mKeyboardWidth == 0)
mKeyboardWidth = res.getDisplayMetrics().widthPixels;
final Locale locale = mSubtypeSwitcher.getInputLocale(); final Locale locale = mSubtypeSwitcher.getInputLocale();
return new KeyboardId( return new KeyboardId(
res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation, mode, res.getResourceEntryName(xmlId), xmlId, charColorId, locale, orientation,
attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, enableShiftLock); mKeyboardWidth, mode, attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey,
enableShiftLock);
} }
private void makeSymbolsKeyboardIds(final int mode, EditorInfo attribute) { private KeyboardId makeSiblingKeyboardId(KeyboardId base, int alphabet, int phone) {
final Locale locale = mSubtypeSwitcher.getInputLocale(); final int xmlId = base.mMode == KeyboardId.MODE_PHONE ? phone : alphabet;
final Resources res = mInputMethodService.getResources(); final String xmlName = mInputMethodService.getResources().getResourceEntryName(xmlId);
final int orientation = res.getConfiguration().orientation; return base.cloneWithNewLayout(xmlName, xmlId);
final int colorScheme = getColorScheme();
final boolean hasVoiceKey = mVoiceKeyEnabled && !mVoiceButtonOnPrimary;
final boolean hasSettingsKey = hasSettingsKey(attribute);
// Note: This comment is only applied for phone number keyboard layout.
// On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch
// between "phone keyboard" and "phone symbols keyboard". But on xlarge device,
// "@integer/key_shift" key code is used for that purpose in order to properly display
// "more" and "locked more" key labels. To achieve these behavior, we should initialize
// mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
// respectively here for xlarge device's layout switching.
int xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols;
final String xmlName = res.getResourceEntryName(xmlId);
mSymbolsId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode,
attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, false);
xmlId = mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift;
mSymbolsShiftedId = new KeyboardId(xmlName, xmlId, colorScheme, locale, orientation, mode,
attribute, hasSettingsKey, mVoiceKeyEnabled, hasVoiceKey, false);
} }
public int getKeyboardMode() { public int getKeyboardMode() {
@ -561,14 +570,12 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return; return;
final LatinKeyboard keyboard; final LatinKeyboard keyboard;
if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) {
mCurrentId = mSymbolsShiftedId; keyboard = getKeyboard(mSymbolsShiftedId);
keyboard = getKeyboard(mCurrentId);
// Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To
// enable the indicator, we need to call setShiftLocked(true). // enable the indicator, we need to call setShiftLocked(true).
keyboard.setShiftLocked(true); keyboard.setShiftLocked(true);
} else { } else {
mCurrentId = mSymbolsId; keyboard = getKeyboard(mSymbolsId);
keyboard = getKeyboard(mCurrentId);
// Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
// indicator, we need to call setShiftLocked(false). // indicator, we need to call setShiftLocked(false).
keyboard.setShiftLocked(false); keyboard.setShiftLocked(false);

View File

@ -462,6 +462,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
return mKeyboardActionListener; return mKeyboardActionListener;
} }
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO: Should notify InputMethodService instead?
KeyboardSwitcher.getInstance().onSizeChanged();
}
/** /**
* Attaches a keyboard to this view. The keyboard can be switched at any time and the * Attaches a keyboard to this view. The keyboard can be switched at any time and the
* view will re-layout itself to accommodate the keyboard. * view will re-layout itself to accommodate the keyboard.

View File

@ -88,8 +88,8 @@ public class LatinKeyboard extends Keyboard {
private static final String SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "small"; private static final String SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "small";
private static final String MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "medium"; private static final String MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "medium";
public LatinKeyboard(Context context, KeyboardId id) { public LatinKeyboard(Context context, KeyboardId id, int width) {
super(context, id.getXmlId(), id); super(context, id.getXmlId(), id, width);
final Resources res = context.getResources(); final Resources res = context.getResources();
mContext = context; mContext = context;

View File

@ -23,8 +23,8 @@ import java.util.List;
public class MiniKeyboard extends Keyboard { public class MiniKeyboard extends Keyboard {
private int mDefaultKeyCoordX; private int mDefaultKeyCoordX;
public MiniKeyboard(Context context, int xmlLayoutResId, KeyboardId id) { public MiniKeyboard(Context context, int xmlLayoutResId, Keyboard parentKeyboard) {
super(context, xmlLayoutResId, id); super(context, xmlLayoutResId, null, parentKeyboard.getMinWidth());
} }
public void setDefaultCoordX(int pos) { public void setDefaultCoordX(int pos) {

View File

@ -185,7 +185,8 @@ public class MiniKeyboardBuilder {
Keyboard parentKeyboard) { Keyboard parentKeyboard) {
final Context context = view.getContext(); final Context context = view.getContext();
mRes = context.getResources(); mRes = context.getResources();
final MiniKeyboard keyboard = new MiniKeyboard(context, layoutTemplateResId, null); final MiniKeyboard keyboard = new MiniKeyboard(
context, layoutTemplateResId, parentKeyboard);
mKeyboard = keyboard; mKeyboard = keyboard;
mPopupCharacters = parentKey.mPopupCharacters; mPopupCharacters = parentKey.mPopupCharacters;

View File

@ -623,6 +623,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} }
} }
@Override
public void onWindowHidden() {
super.onWindowHidden();
KeyboardView inputView = mKeyboardSwitcher.getInputView();
if (inputView != null) inputView.closing();
}
@Override @Override
public void onFinishInput() { public void onFinishInput() {
super.onFinishInput(); super.onFinishInput();
@ -809,7 +816,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (isExtractViewShown()) { if (isExtractViewShown()) {
// No need to have extra space to show the key preview. // No need to have extra space to show the key preview.
mCandidateViewContainer.setMinimumHeight(0); mCandidateViewContainer.setMinimumHeight(0);
super.setCandidatesViewShown(shown); super.setCandidatesViewShown(shouldShowCandidates);
} else { } else {
// We must control the visibility of the suggestion strip in order to avoid clipped // We must control the visibility of the suggestion strip in order to avoid clipped
// key previews, even when we don't show the suggestion strip. // key previews, even when we don't show the suggestion strip.

View File

@ -36,7 +36,7 @@ public class SuggestHelper {
// Use null as the locale for Suggest so as to force it to use the internal dictionary // Use null as the locale for Suggest so as to force it to use the internal dictionary
// (and not try to find a dictionary provider for a specified locale) // (and not try to find a dictionary provider for a specified locale)
mSuggest = new Suggest(context, dictionaryId, null); mSuggest = new Suggest(context, dictionaryId, null);
mKeyboard = new LatinKeyboard(context, keyboardId); mKeyboard = new LatinKeyboard(context, keyboardId, keyboardId.mWidth);
mKeyDetector = new KeyDetector(); mKeyDetector = new KeyDetector();
init(); init();
} }
@ -44,7 +44,7 @@ public class SuggestHelper {
protected SuggestHelper(Context context, File dictionaryPath, long startOffset, long length, protected SuggestHelper(Context context, File dictionaryPath, long startOffset, long length,
KeyboardId keyboardId) { KeyboardId keyboardId) {
mSuggest = new Suggest(context, dictionaryPath, startOffset, length, null); mSuggest = new Suggest(context, dictionaryPath, startOffset, length, null);
mKeyboard = new LatinKeyboard(context, keyboardId); mKeyboard = new LatinKeyboard(context, keyboardId, keyboardId.mWidth);
mKeyDetector = new KeyDetector(); mKeyDetector = new KeyDetector();
init(); init();
} }

View File

@ -38,10 +38,11 @@ public class SuggestTestsBase extends AndroidTestCase {
mTestPackageFile = new File(getTestContext().getApplicationInfo().sourceDir); mTestPackageFile = new File(getTestContext().getApplicationInfo().sourceDir);
} }
protected static KeyboardId createKeyboardId(Locale locale) { protected KeyboardId createKeyboardId(Locale locale) {
final int displayWidth = getContext().getResources().getDisplayMetrics().widthPixels;
return new KeyboardId(locale.toString() + " keyboard", return new KeyboardId(locale.toString() + " keyboard",
com.android.inputmethod.latin.R.xml.kbd_qwerty, KeyboardView.COLOR_SCHEME_WHITE, com.android.inputmethod.latin.R.xml.kbd_qwerty, KeyboardView.COLOR_SCHEME_WHITE,
locale, Configuration.ORIENTATION_LANDSCAPE, KeyboardId.MODE_TEXT, locale, displayWidth, Configuration.ORIENTATION_LANDSCAPE, KeyboardId.MODE_TEXT,
new EditorInfo(), false, false, false, false); new EditorInfo(), false, false, false, false);
} }