Language switching with slide gesture on spacebar. Bug: 2331173

Shows the language on the spacebar and in the preview bubble. Allows
dragging of the spacebar from side to side to switch to previous or
next languages.
This commit is contained in:
Amith Yamasani 2010-01-29 20:09:49 -08:00
parent 41a5197295
commit 3f7d75060a
6 changed files with 533 additions and 81 deletions

View file

@ -77,6 +77,7 @@ public class KeyboardSwitcher {
private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
private int mLastDisplayWidth;
private LanguageSwitcher mLanguageSwitcher;
private Locale mInputLocale;
private boolean mEnableMultipleLanguages;
@ -94,9 +95,10 @@ public class KeyboardSwitcher {
* @param locale the current input locale, or null for default locale with no locale
* button.
*/
void setInputLocale(Locale locale, boolean enableMultipleLanguages) {
mInputLocale = locale;
mEnableMultipleLanguages = enableMultipleLanguages;
void setLanguageSwitcher(LanguageSwitcher languageSwitcher) {
mLanguageSwitcher = languageSwitcher;
mInputLocale = mLanguageSwitcher.getInputLocale();
mEnableMultipleLanguages = mLanguageSwitcher.getLocaleCount() > 1;
}
void setInputView(LatinKeyboardView inputView) {
@ -195,11 +197,6 @@ public class KeyboardSwitcher {
}
mCurrentId = id;
if (mEnableMultipleLanguages) {
keyboard.setLanguage(mInputLocale);
} else {
keyboard.setLanguage(null);
}
mInputView.setKeyboard(keyboard);
keyboard.setShifted(false);
keyboard.setShiftLocked(keyboard.isShiftLocked());
@ -215,6 +212,7 @@ public class KeyboardSwitcher {
orig.updateConfiguration(conf, null);
LatinKeyboard keyboard = new LatinKeyboard(
mContext, id.mXml, id.mKeyboardMode, id.mHasVoice);
keyboard.setLanguageSwitcher(mLanguageSwitcher);
if (id.mKeyboardMode == KEYBOARDMODE_NORMAL
|| id.mKeyboardMode == KEYBOARDMODE_URL
|| id.mKeyboardMode == KEYBOARDMODE_IM

View file

@ -0,0 +1,165 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.latin;
import java.util.Locale;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
/**
* Keeps track of list of selected input languages and the current
* input language that the user has selected.
*/
public class LanguageSwitcher {
private Locale[] mLocales;
private LatinIME mIme;
private String[] mSelectedLanguageArray;
private String mSelectedLanguages;
private int mCurrentIndex = 0;
private String mDefaultInputLanguage;
private Locale mDefaultInputLocale;
public LanguageSwitcher(LatinIME ime) {
mIme = ime;
mLocales = new Locale[0];
}
public Locale[] getLocales() {
return mLocales;
}
public int getLocaleCount() {
return mLocales.length;
}
/**
* Loads the currently selected input languages from shared preferences.
* @param sp
* @return whether there was any change
*/
public boolean loadLocales(SharedPreferences sp) {
String selectedLanguages = sp.getString(LatinIME.PREF_SELECTED_LANGUAGES, null);
String currentLanguage = sp.getString(LatinIME.PREF_INPUT_LANGUAGE, null);
if (selectedLanguages == null || selectedLanguages.length() < 1) {
loadDefaults();
if (mLocales.length == 0) {
return false;
}
mLocales = new Locale[0];
return true;
}
if (selectedLanguages.equals(mSelectedLanguages)) {
return false;
}
mSelectedLanguageArray = selectedLanguages.split(",");
mSelectedLanguages = selectedLanguages; // Cache it for comparison later
constructLocales();
mCurrentIndex = 0;
if (currentLanguage != null) {
// Find the index
mCurrentIndex = 0;
for (int i = 0; i < mLocales.length; i++) {
if (mSelectedLanguageArray[i].equals(currentLanguage)) {
mCurrentIndex = i;
break;
}
}
// If we didn't find the index, use the first one
}
return true;
}
private void loadDefaults() {
mDefaultInputLocale = mIme.getResources().getConfiguration().locale;
mDefaultInputLanguage = mDefaultInputLocale.getLanguage() + "_"
+ mDefaultInputLocale.getCountry();
}
private void constructLocales() {
mLocales = new Locale[mSelectedLanguageArray.length];
for (int i = 0; i < mLocales.length; i++) {
mLocales[i] = new Locale(mSelectedLanguageArray[i]);
}
}
/**
* Returns the currently selected input language code, or the display language code if
* no specific locale was selected for input.
*/
public String getInputLanguage() {
if (getLocaleCount() == 0) return mDefaultInputLanguage;
return mSelectedLanguageArray[mCurrentIndex];
}
/**
* Returns the currently selected input locale, or the display locale if no specific
* locale was selected for input.
* @return
*/
public Locale getInputLocale() {
if (getLocaleCount() == 0) return mDefaultInputLocale;
return mLocales[mCurrentIndex];
}
/**
* Returns the next input locale in the list. Wraps around to the beginning of the
* list if we're at the end of the list.
* @return
*/
public Locale getNextInputLocale() {
if (getLocaleCount() == 0) return mDefaultInputLocale;
return mLocales[(mCurrentIndex + 1) % mLocales.length];
}
/**
* Returns the previous input locale in the list. Wraps around to the end of the
* list if we're at the beginning of the list.
* @return
*/
public Locale getPrevInputLocale() {
if (getLocaleCount() == 0) return mDefaultInputLocale;
return mLocales[(mCurrentIndex - 1 + mLocales.length) % mLocales.length];
}
public void reset() {
mCurrentIndex = 0;
}
public void next() {
mCurrentIndex++;
if (mCurrentIndex >= mLocales.length) mCurrentIndex = 0; // Wrap around
}
public void prev() {
mCurrentIndex--;
if (mCurrentIndex < 0) mCurrentIndex = mLocales.length - 1; // Wrap around
}
public void persist() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mIme);
Editor editor = sp.edit();
editor.putString(LatinIME.PREF_INPUT_LANGUAGE, getInputLanguage());
editor.commit();
}
}

View file

@ -178,6 +178,7 @@ public class LatinIME extends InputMethodService
Resources mResources;
private String mLocale;
private LanguageSwitcher mLanguageSwitcher;
private StringBuilder mComposing = new StringBuilder();
private WordComposer mWord = new WordComposer();
@ -244,10 +245,6 @@ public class LatinIME extends InputMethodService
List<String> candidates;
Map<String, List<CharSequence>> alternatives;
}
private int mCurrentInputLocale = 0;
private String mInputLanguage;
private String[] mSelectedLanguageArray;
private String mSelectedLanguagesList;
private boolean mRefreshKeyboardRequired;
Handler mHandler = new Handler() {
@ -285,18 +282,19 @@ public class LatinIME extends InputMethodService
@Override public void onCreate() {
super.onCreate();
//setStatusIcon(R.drawable.ime_qwerty);
mKeyboardSwitcher = new KeyboardSwitcher(this, this);
mResources = getResources();
final Configuration conf = mResources.getConfiguration();
mInputLanguage = getPersistedInputLanguage();
mSelectedLanguagesList = getSelectedInputLanguages();
boolean enableMultipleLanguages = mSelectedLanguagesList != null
&& mSelectedLanguagesList.split(",").length > 1;
if (mInputLanguage == null) {
mInputLanguage = conf.locale.toString();
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
mLanguageSwitcher = new LanguageSwitcher(this);
mLanguageSwitcher.loadLocales(prefs);
mKeyboardSwitcher = new KeyboardSwitcher(this, this);
mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
boolean enableMultipleLanguages = mLanguageSwitcher.getLocaleCount() > 0;
String inputLanguage = mLanguageSwitcher.getInputLanguage();
if (inputLanguage == null) {
inputLanguage = conf.locale.toString();
}
initSuggest(mInputLanguage);
mKeyboardSwitcher.setInputLocale(conf.locale, enableMultipleLanguages);
initSuggest(inputLanguage);
mOrientation = conf.orientation;
mVibrateDuration = mResources.getInteger(R.integer.vibrate_duration_ms);
@ -317,8 +315,7 @@ public class LatinIME extends InputMethodService
}
});
}
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this);
prefs.registerOnSharedPreferenceChangeListener(this);
}
private void initSuggest(String locale) {
@ -429,7 +426,7 @@ public class LatinIME extends InputMethodService
if (mRefreshKeyboardRequired) {
mRefreshKeyboardRequired = false;
toggleLanguage(true);
toggleLanguage(true, true);
}
mKeyboardSwitcher.makeKeyboards(false);
@ -791,8 +788,7 @@ public class LatinIME extends InputMethodService
if (mKeyboardSwitcher == null) {
mKeyboardSwitcher = new KeyboardSwitcher(this, this);
}
mKeyboardSwitcher.setInputLocale(new Locale(mInputLanguage),
getSelectedInputLanguages() != null);
mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
if (mInputView != null) {
mKeyboardSwitcher.setVoiceMode(mEnableVoice, mVoiceOnPrimary);
}
@ -919,7 +915,10 @@ public class LatinIME extends InputMethodService
showOptionsMenu();
break;
case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
toggleLanguage(false);
toggleLanguage(false, true);
break;
case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
toggleLanguage(false, false);
break;
case LatinKeyboardView.KEYCODE_SHIFT_LONGPRESS:
if (mCapsLock) {
@ -1514,27 +1513,30 @@ public class LatinIME extends InputMethodService
}
}
private void toggleLanguage(boolean reset) {
final String [] languages = mSelectedLanguageArray;
if (reset) mCurrentInputLocale = -1;
mCurrentInputLocale = (mCurrentInputLocale + 1)
% (languages != null ? languages.length : 1);
mInputLanguage = languages != null ? languages[mCurrentInputLocale] :
getResources().getConfiguration().locale.getLanguage();
private void toggleLanguage(boolean reset, boolean next) {
if (reset) {
mLanguageSwitcher.reset();
} else {
if (next) {
mLanguageSwitcher.next();
} else {
mLanguageSwitcher.prev();
}
}
int currentKeyboardMode = mKeyboardSwitcher.getKeyboardMode();
reloadKeyboards();
mKeyboardSwitcher.makeKeyboards(true);
mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0,
mEnableVoiceButton && mEnableVoice);
initSuggest(mInputLanguage);
persistInputLanguage(mInputLanguage);
initSuggest(mLanguageSwitcher.getInputLanguage());
mLanguageSwitcher.persist();
updateShiftKeyState(getCurrentInputEditorInfo());
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (PREF_SELECTED_LANGUAGES.equals(key)) {
updateSelectedLanguages(sharedPreferences.getString(key, null));
mLanguageSwitcher.loadLocales(sharedPreferences);
mRefreshKeyboardRequired = true;
}
}
@ -1556,6 +1558,8 @@ public class LatinIME extends InputMethodService
}
public void onRelease(int primaryCode) {
// Reset any drag flags in the keyboard
((LatinKeyboard) mInputView.getKeyboard()).keyReleased();
//vibrate();
}
@ -1750,16 +1754,7 @@ public class LatinIME extends InputMethodService
mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE,
mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
updateCorrectionMode();
String languageList = sp.getString(PREF_SELECTED_LANGUAGES, null);
updateSelectedLanguages(languageList);
}
private void updateSelectedLanguages(String languageList) {
if (languageList != null && languageList.length() > 1) {
mSelectedLanguageArray = languageList.split(",");
} else {
mSelectedLanguageArray = null;
}
mLanguageSwitcher.loadLocales(sp);
}
private String getPersistedInputLanguage() {
@ -1767,13 +1762,6 @@ public class LatinIME extends InputMethodService
return sp.getString(PREF_INPUT_LANGUAGE, null);
}
private void persistInputLanguage(String inputLanguage) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
Editor editor = sp.edit();
editor.putString(PREF_INPUT_LANGUAGE, inputLanguage);
editor.commit();
}
private String getSelectedInputLanguages() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
return sp.getString(PREF_SELECTED_LANGUAGES, null);

View file

@ -16,19 +16,26 @@
package com.android.inputmethod.latin;
import java.util.List;
import java.util.Locale;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Paint.Align;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard;
import android.text.TextPaint;
import android.view.ViewConfiguration;
import android.view.inputmethod.EditorInfo;
public class LatinKeyboard extends Keyboard {
@ -38,18 +45,29 @@ public class LatinKeyboard extends Keyboard {
private Drawable mOldShiftIcon;
private Drawable mOldShiftPreviewIcon;
private Drawable mSpaceIcon;
private Drawable mSpacePreviewIcon;
private Drawable mMicIcon;
private Drawable mMicPreviewIcon;
private Drawable m123MicIcon;
private Drawable m123MicPreviewIcon;
private Drawable mButtonArrowLeftIcon;
private Drawable mButtonArrowRightIcon;
private Key mShiftKey;
private Key mEnterKey;
private Key mF1Key;
private Key mSpaceKey;
private int mSpaceKeyIndex = -1;
private int mSpaceDragStartX;
private int mSpaceDragLastDiff;
/* package */ Locale mLocale;
private LanguageSwitcher mLanguageSwitcher;
private Resources mRes;
private Context mContext;
private int mMode;
private boolean mHasVoice;
private boolean mCurrentlyInSpace;
private SlidingLocaleDrawable mSlidingLocaleIcon;
private Rect mBounds = new Rect();
private int mExtensionResId;
@ -59,6 +77,8 @@ public class LatinKeyboard extends Keyboard {
private int mShiftState = SHIFT_OFF;
private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
static int sSpacebarVerticalCorrection;
public LatinKeyboard(Context context, int xmlLayoutResId) {
@ -68,6 +88,7 @@ public class LatinKeyboard extends Keyboard {
public LatinKeyboard(Context context, int xmlLayoutResId, int mode, boolean hasVoice) {
super(context, xmlLayoutResId, mode);
final Resources res = context.getResources();
mContext = context;
mMode = mode;
mRes = res;
mHasVoice = hasVoice;
@ -77,11 +98,15 @@ public class LatinKeyboard extends Keyboard {
mShiftLockPreviewIcon.getIntrinsicWidth(),
mShiftLockPreviewIcon.getIntrinsicHeight());
mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space);
mSpacePreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_space);
mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic);
mMicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_mic);
mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left);
mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right);
sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
R.dimen.spacebar_vertical_correction);
setF1Key();
mSpaceKeyIndex = indexOf((int) ' ');
}
public LatinKeyboard(Context context, int layoutTemplateResId,
@ -237,7 +262,6 @@ public class LatinKeyboard extends Keyboard {
private void setF1Key() {
if (mF1Key == null) return;
System.err.println("Setting F1 key");
if (!mHasVoice) {
mF1Key.label = ",";
mF1Key.codes = new int[] { ',' };
@ -260,34 +284,179 @@ public class LatinKeyboard extends Keyboard {
canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
Paint paint = new Paint();
paint.setAntiAlias(true);
// TODO: Make the text size a customizable attribute
paint.setTextSize(18);
// Get the text size from the theme
paint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Small, 14));
paint.setTextAlign(Align.CENTER);
// Draw a drop shadow for the text
paint.setShadowLayer(1f, 0, 0, 0xFF000000);
paint.setShadowLayer(2f, 0, 0, 0xFF000000);
paint.setColor(0xFF808080);
canvas.drawText(mLocale.getDisplayLanguage(mLocale),
buffer.getWidth() / 2, - paint.ascent() + 2, paint);
final String language = getInputLanguage(mSpaceKey.width, paint);
final int ascent = (int) -paint.ascent();
canvas.drawText(language,
buffer.getWidth() / 2, ascent, paint);
// Put arrows on either side of the text
if (mLanguageSwitcher.getLocaleCount() > 1) {
Rect bounds = new Rect();
paint.getTextBounds(language, 0, language.length(), bounds);
drawButtonArrow(mButtonArrowLeftIcon, canvas,
(mSpaceKey.width - bounds.right) / 2
- mButtonArrowLeftIcon.getIntrinsicWidth(),
(int) paint.getTextSize());
drawButtonArrow(mButtonArrowRightIcon, canvas,
(mSpaceKey.width + bounds.right) / 2, (int) paint.getTextSize());
}
// Draw the spacebar icon at the bottom
int x = (buffer.getWidth() - mSpaceIcon.getIntrinsicWidth()) / 2;
int y = buffer.getHeight() - mSpaceIcon.getIntrinsicHeight();
mSpaceIcon.setBounds(x, y,
x + mSpaceIcon.getIntrinsicWidth(), y + mSpaceIcon.getIntrinsicHeight());
mSpaceIcon.draw(canvas);
mSpaceKey.icon = new BitmapDrawable(mRes, buffer);
mSpaceKey.repeatable = false;
mSpaceKey.repeatable = mLanguageSwitcher.getLocaleCount() < 2;
} else {
mSpaceKey.icon = mRes.getDrawable(R.drawable.sym_keyboard_space);
mSpaceKey.repeatable = true;
}
}
public void setLanguage(Locale locale) {
private void drawButtonArrow(Drawable arrow, Canvas canvas, int x, int bottomY) {
arrow.setBounds(x, bottomY - arrow.getIntrinsicHeight(), x + arrow.getIntrinsicWidth(),
bottomY);
arrow.draw(canvas);
}
private String getInputLanguage(int widthAvail, Paint paint) {
return chooseDisplayName(mLanguageSwitcher.getInputLocale(), widthAvail, paint);
}
private String getNextInputLanguage(int widthAvail, Paint paint) {
return chooseDisplayName(mLanguageSwitcher.getNextInputLocale(), widthAvail, paint);
}
private String getPrevInputLanguage(int widthAvail, Paint paint) {
return chooseDisplayName(mLanguageSwitcher.getPrevInputLocale(), widthAvail, paint);
}
private String chooseDisplayName(Locale locale, int widthAvail, Paint paint) {
if (widthAvail < (int) (.35 * getMinWidth())) {
return locale.getLanguage().substring(0, 2).toUpperCase(locale);
} else {
return locale.getDisplayLanguage(locale);
}
}
private void updateLocaleDrag(int diff) {
if (mSlidingLocaleIcon == null) {
mSlidingLocaleIcon = new SlidingLocaleDrawable(mSpacePreviewIcon, mSpaceKey.width,
mSpacePreviewIcon.getIntrinsicHeight());
mSlidingLocaleIcon.setBounds(0, 0, mSpaceKey.width,
mSpacePreviewIcon.getIntrinsicHeight());
mSpaceKey.iconPreview = mSlidingLocaleIcon;
}
mSlidingLocaleIcon.setDiff(diff);
if (Math.abs(diff) == Integer.MAX_VALUE) {
mSpaceKey.iconPreview = mSpacePreviewIcon;
} else {
mSpaceKey.iconPreview = mSlidingLocaleIcon;
}
mSpaceKey.iconPreview.invalidateSelf();
}
public int getLanguageChangeDirection() {
if (mSpaceKey == null || mLanguageSwitcher.getLocaleCount() < 2
|| Math.abs(mSpaceDragLastDiff) < mSpaceKey.width * SPACEBAR_DRAG_THRESHOLD ) {
return 0; // No change
}
return mSpaceDragLastDiff > 0 ? 1 : -1;
}
public void setLanguageSwitcher(LanguageSwitcher switcher) {
mLanguageSwitcher = switcher;
Locale locale = mLanguageSwitcher.getLocaleCount() > 0
? mLanguageSwitcher.getInputLocale()
: null;
if (mLocale != null && mLocale.equals(locale)) return;
mLocale = locale;
updateSpaceBarForLocale();
}
static class LatinKey extends Keyboard.Key {
boolean isCurrentlyInSpace() {
return mCurrentlyInSpace;
}
void keyReleased() {
mCurrentlyInSpace = false;
mSpaceDragLastDiff = 0;
if (mSpaceKey != null) {
updateLocaleDrag(Integer.MAX_VALUE);
}
}
/**
* Does the magic of locking the touch gesture into the spacebar when
* switching input languages.
*/
boolean isInside(LatinKey key, int x, int y) {
final int code = key.codes[0];
if (code == KEYCODE_SHIFT ||
code == KEYCODE_DELETE) {
y -= key.height / 10;
if (code == KEYCODE_SHIFT) x += key.width / 6;
if (code == KEYCODE_DELETE) x -= key.width / 6;
} else if (code == LatinIME.KEYCODE_SPACE) {
y += LatinKeyboard.sSpacebarVerticalCorrection;
if (mLanguageSwitcher.getLocaleCount() > 1) {
if (mCurrentlyInSpace) {
int diff = x - mSpaceDragStartX;
if (Math.abs(diff - mSpaceDragLastDiff) > 0) {
updateLocaleDrag(diff);
}
mSpaceDragLastDiff = diff;
return true;
} else {
boolean insideSpace = key.isInsideSuper(x, y);
if (insideSpace) {
mCurrentlyInSpace = true;
mSpaceDragStartX = x;
updateLocaleDrag(0);
}
return insideSpace;
}
}
}
// Lock into the spacebar
if (mCurrentlyInSpace) return false;
return key.isInsideSuper(x, y);
}
@Override
public int[] getNearestKeys(int x, int y) {
if (mCurrentlyInSpace) {
return new int[] { mSpaceKeyIndex };
} else {
return super.getNearestKeys(x, y);
}
}
private int indexOf(int code) {
List<Key> keys = getKeys();
int count = keys.size();
for (int i = 0; i < count; i++) {
if (keys.get(i).codes[0] == code) return i;
}
return -1;
}
private int getTextSizeFromTheme(int style, int defValue) {
TypedArray array = mContext.getTheme().obtainStyledAttributes(
style, new int[] { android.R.attr.textSize });
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
return textSize;
}
class LatinKey extends Keyboard.Key {
private boolean mShiftLockEnabled;
@ -318,16 +487,130 @@ public class LatinKeyboard extends Keyboard {
*/
@Override
public boolean isInside(int x, int y) {
final int code = codes[0];
if (code == KEYCODE_SHIFT ||
code == KEYCODE_DELETE) {
y -= height / 10;
if (code == KEYCODE_SHIFT) x += width / 6;
if (code == KEYCODE_DELETE) x -= width / 6;
} else if (code == LatinIME.KEYCODE_SPACE) {
y += LatinKeyboard.sSpacebarVerticalCorrection;
}
return LatinKeyboard.this.isInside(this, x, y);
}
boolean isInsideSuper(int x, int y) {
return super.isInside(x, y);
}
}
/**
* Animation to be displayed on the spacebar preview popup when switching
* languages by swiping the spacebar. It draws the current, previous and
* next languages and moves them by the delta of touch movement on the spacebar.
*/
class SlidingLocaleDrawable extends Drawable {
private int mWidth;
private int mHeight;
private Drawable mBackground;
private int mDiff;
private TextPaint mTextPaint;
private int mMiddleX;
private int mAscent;
private Drawable mLeftDrawable;
private Drawable mRightDrawable;
private boolean mHitThreshold;
private int mThreshold;
private String mCurrentLanguage;
private String mNextLanguage;
private String mPrevLanguage;
public SlidingLocaleDrawable(Drawable background, int width, int height) {
mBackground = background;
mBackground.setBounds(0, 0,
mBackground.getIntrinsicWidth(), mBackground.getIntrinsicHeight());
mWidth = width;
mHeight = height;
mTextPaint = new TextPaint();
int textSize = getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18);
mTextPaint.setTextSize(textSize);
mTextPaint.setColor(0);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setAlpha(255);
mTextPaint.setAntiAlias(true);
mAscent = (int) mTextPaint.ascent();
mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
mLeftDrawable =
mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_left);
mRightDrawable =
mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_right);
mLeftDrawable.setBounds(0, 0,
mLeftDrawable.getIntrinsicWidth(), mLeftDrawable.getIntrinsicHeight());
mRightDrawable.setBounds(mWidth - mRightDrawable.getIntrinsicWidth(), 0,
mWidth, mRightDrawable.getIntrinsicHeight());
mThreshold = ViewConfiguration.get(mContext).getScaledTouchSlop();
}
void setDiff(int diff) {
if (diff == Integer.MAX_VALUE) {
mHitThreshold = false;
mCurrentLanguage = null;
return;
}
mDiff = diff;
if (mDiff > mWidth) mDiff = mWidth;
if (mDiff < -mWidth) mDiff = -mWidth;
if (Math.abs(mDiff) > mThreshold) mHitThreshold = true;
invalidateSelf();
}
@Override
public void draw(Canvas canvas) {
canvas.save();
if (mHitThreshold) {
mTextPaint.setColor(0);
canvas.clipRect(0, 0, mWidth, mHeight);
int alpha = (255 * Math.max(0, mWidth / 2 - Math.abs(mDiff))) / (mWidth / 2);
mTextPaint.setAlpha(alpha);
if (mCurrentLanguage == null) {
mCurrentLanguage = getInputLanguage(mWidth, mTextPaint);
mNextLanguage = getNextInputLanguage(mWidth, mTextPaint);
mPrevLanguage = getPrevInputLanguage(mWidth, mTextPaint);
}
canvas.drawText(mCurrentLanguage,
mWidth / 2 + mDiff, -mAscent + 4, mTextPaint);
mTextPaint.setAlpha(255 - alpha);
canvas.drawText(mNextLanguage,
mDiff - mWidth / 2, -mAscent + 4, mTextPaint);
canvas.drawText(mPrevLanguage,
mDiff + mWidth + mWidth / 2, -mAscent + 4, mTextPaint);
mLeftDrawable.draw(canvas);
mRightDrawable.draw(canvas);
}
if (mBackground != null) {
canvas.translate(mMiddleX, 0);
mBackground.draw(canvas);
}
canvas.restore();
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public void setAlpha(int alpha) {
// Ignore
}
@Override
public void setColorFilter(ColorFilter cf) {
// Ignore
}
@Override
public int getIntrinsicWidth() {
return mWidth;
}
@Override
public int getIntrinsicHeight() {
return mHeight;
}
}
}

View file

@ -38,9 +38,15 @@ public class LatinKeyboardView extends KeyboardView {
static final int KEYCODE_VOICE = -102;
static final int KEYCODE_F1 = -103;
static final int KEYCODE_NEXT_LANGUAGE = -104;
static final int KEYCODE_PREV_LANGUAGE = -105;
private Keyboard mPhoneKeyboard;
private boolean mExtensionVisible;
private LatinKeyboardView mExtension;
private PopupWindow mExtensionPopup;
private boolean mFirstEvent;
public LatinKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@ -66,22 +72,33 @@ public class LatinKeyboardView extends KeyboardView {
// Long pressing on 0 in phone number keypad gives you a '+'.
getOnKeyboardActionListener().onKey('+', null);
return true;
} else if (key.codes[0] == ' ' && ((LatinKeyboard)getKeyboard()).mLocale != null) {
getOnKeyboardActionListener().onKey(KEYCODE_NEXT_LANGUAGE, null);
return true;
} else {
return super.onLongPress(key);
}
}
private boolean mExtensionVisible;
private LatinKeyboardView mExtension;
private PopupWindow mExtensionPopup;
private boolean mFirstEvent;
@Override
public boolean onTouchEvent(MotionEvent me) {
if (((LatinKeyboard) getKeyboard()).getExtension() == 0) {
LatinKeyboard keyboard = (LatinKeyboard) getKeyboard();
// Reset any bounding box controls in the keyboard
if (me.getAction() == MotionEvent.ACTION_DOWN) {
keyboard.keyReleased();
}
if (me.getAction() == MotionEvent.ACTION_UP) {
int languageDirection = keyboard.getLanguageChangeDirection();
if (languageDirection != 0) {
getOnKeyboardActionListener().onKey(
languageDirection == 1 ? KEYCODE_NEXT_LANGUAGE : KEYCODE_PREV_LANGUAGE,
null);
me.setAction(MotionEvent.ACTION_CANCEL);
keyboard.keyReleased();
return super.onTouchEvent(me);
}
}
// If we don't have an extension keyboard, don't go any further.
if (keyboard.getExtension() == 0) {
return super.onTouchEvent(me);
}
if (me.getY() < 0) {

View file

@ -123,6 +123,7 @@ public class TextEntryState {
}
public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord) {
if (typedWord == null) return;
if (!typedWord.equals(actualWord)) {
sAutoSuggestCount++;
}