From 6fb97bf71cee2a0775410a05478ed6a667aa847f Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 15 Apr 2011 16:33:46 +0900 Subject: [PATCH] Don't show spacebar preview if key preview is disabled This change also introduces soft reference cache of spacebar Drawable. Bug: 4307333 Change-Id: I4d2c500bb47d794aa4f8dfa6ec415dbcb9ab0b74 --- .../inputmethod/keyboard/Keyboard.java | 40 +++++--- .../inputmethod/keyboard/KeyboardView.java | 13 +-- .../inputmethod/keyboard/LatinKeyboard.java | 91 ++++++++++++++----- .../keyboard/SlidingLocaleDrawable.java | 4 +- 4 files changed, 97 insertions(+), 51 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 9b8d75e8f..fdfe282c3 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -128,6 +128,8 @@ public class Keyboard { /** Height of keyboard */ private int mKeyboardHeight; + private int mMostCommonKeyWidth = 0; + public final KeyboardId mId; // Variables for pre-computing nearest keys. @@ -411,21 +413,33 @@ public class Keyboard { * @return The most common key width in the keyboard */ public int getMostCommonKeyWidth() { - final HashMap histogram = new HashMap(); - int maxCount = 0; - int mostCommonWidth = 0; - for (final Key key : mKeys) { - final Integer width = key.mWidth + key.mGap; - Integer count = histogram.get(width); - if (count == null) - count = 0; - histogram.put(width, ++count); - if (count > maxCount) { - maxCount = count; - mostCommonWidth = width; + if (mMostCommonKeyWidth == 0) { + final HashMap histogram = new HashMap(); + int maxCount = 0; + int mostCommonWidth = 0; + for (final Key key : mKeys) { + final Integer width = key.mWidth + key.mGap; + Integer count = histogram.get(width); + if (count == null) + count = 0; + histogram.put(width, ++count); + if (count > maxCount) { + maxCount = count; + mostCommonWidth = width; + } } + mMostCommonKeyWidth = mostCommonWidth; } - return mostCommonWidth; + return mMostCommonKeyWidth; + } + + /** + * Return true if spacebar needs showing preview even when "popup on keypress" is off. + * @param keyIndex index of the pressing key + * @return true if spacebar needs showing preview + */ + public boolean needSpacebarPreview(int keyIndex) { + return false; } private void loadKeyboard(Context context, int xmlLayoutResId) { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index a140a974d..3550dcbb0 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -18,7 +18,6 @@ package com.android.inputmethod.keyboard; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SubtypeSwitcher; import android.content.Context; import android.content.pm.PackageManager; @@ -224,7 +223,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { public void popupPreview(long delay, int keyIndex, PointerTracker tracker) { removeMessages(MSG_POPUP_PREVIEW); - if (mPreviewText.getVisibility() == VISIBLE) { + if (mPreviewText.getVisibility() == VISIBLE || delay == 0) { // Show right away, if it's already visible and finger is moving around showKey(keyIndex, tracker); } else { @@ -889,15 +888,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { public void showPreview(int keyIndex, PointerTracker tracker) { int oldKeyIndex = mOldPreviewKeyIndex; mOldPreviewKeyIndex = keyIndex; - // We should re-draw popup preview when 1) we need to hide the preview, 2) we will show - // the space key preview and 3) pointer moves off the space key to other letter key, we - // should hide the preview of the previous key. - final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null) - || (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher() - && SubtypeSwitcher.getInstance().needsToDisplayLanguage() - && (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex))); - // If key changed and preview is on or the key is space (language switch is enabled) - if (oldKeyIndex != keyIndex && (mShowPreview || (hidePreviewOrShowSpaceKeyPreview))) { + if ((mShowPreview && oldKeyIndex != keyIndex) || mKeyboard.needSpacebarPreview(keyIndex)) { if (keyIndex == KeyDetector.NOT_A_KEY) { mHandler.cancelPopupPreview(); mHandler.dismissPreview(mDelayAfterPreview); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index 9d9793e1e..3a5dbd2de 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -26,6 +26,9 @@ import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.PorterDuff; @@ -33,15 +36,18 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import java.lang.ref.SoftReference; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Locale; // TODO: We should remove this class public class LatinKeyboard extends Keyboard { - public static final int OPACITY_FULLY_OPAQUE = 255; private static final int SPACE_LED_LENGTH_PERCENT = 80; private final Context mContext; + private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance(); /* Space key and its icons, drawables and colors. */ private final Key mSpaceKey; @@ -59,14 +65,18 @@ public class LatinKeyboard extends Keyboard { private int mSpaceDragLastDiff; private boolean mCurrentlyInSpace; private SlidingLocaleDrawable mSlidingLocaleIcon; + private final HashMap> mSpaceDrawableCache = + new HashMap>(); /* Shortcut key and its icons if available */ private final Key mShortcutKey; private final Drawable mEnabledShortcutIcon; private final Drawable mDisabledShortcutIcon; - private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f; - // Minimum width of space key preview (proportional to keyboard width) + // Minimum width of spacebar dragging to trigger the language switch (represented by the number + // of the most common key width of this keyboard). + private static final int SPACEBAR_DRAG_WIDTH = 3; + // Minimum width of space key preview (proportional to keyboard width). private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f; // Height in space key the language name will be drawn. (proportional to space key height) public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f; @@ -137,6 +147,12 @@ public class LatinKeyboard extends Keyboard { return newColor; } + private static ColorFilter getSpacebarDrawableFilter(float fadeFactor) { + final ColorMatrix colorMatrix = new ColorMatrix(); + colorMatrix.setScale(1, 1, 1, fadeFactor); + return new ColorMatrixColorFilter(colorMatrix); + } + public void updateShortcutKey(boolean available, LatinKeyboardView view) { if (mShortcutKey == null) return; @@ -157,19 +173,14 @@ public class LatinKeyboard extends Keyboard { private void updateSpacebarForLocale(boolean isAutoCorrection) { if (mSpaceKey == null) return; - final Resources res = mContext.getResources(); // If application locales are explicitly selected. - if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) { - mSpaceKey.setIcon(new BitmapDrawable(res, - drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection))); + if (mSubtypeSwitcher.needsToDisplayLanguage()) { + mSpaceKey.setIcon(getSpaceDrawable( + mSubtypeSwitcher.getInputLocale(), isAutoCorrection)); + } else if (isAutoCorrection) { + mSpaceKey.setIcon(getSpaceDrawable(null, true)); } else { - // sym_keyboard_space_led can be shared with Black and White symbol themes. - if (isAutoCorrection) { - mSpaceKey.setIcon(new BitmapDrawable(res, - drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection))); - } else { - mSpaceKey.setIcon(mSpaceIcon); - } + mSpaceKey.setIcon(mSpaceIcon); } } @@ -223,19 +234,31 @@ public class LatinKeyboard extends Keyboard { return language; } - private Bitmap drawSpacebar(int opacity, boolean isAutoCorrection) { + private BitmapDrawable getSpaceDrawable(Locale locale, boolean isAutoCorrection) { + final Integer hashCode = Arrays.hashCode( + new Object[] { locale, isAutoCorrection, mSpacebarTextFadeFactor }); + final SoftReference ref = mSpaceDrawableCache.get(hashCode); + BitmapDrawable drawable = (ref == null) ? null : ref.get(); + if (drawable == null) { + drawable = new BitmapDrawable(mContext.getResources(), drawSpacebar( + locale, isAutoCorrection, mSpacebarTextFadeFactor)); + mSpaceDrawableCache.put(hashCode, new SoftReference(drawable)); + } + return drawable; + } + + private Bitmap drawSpacebar(Locale inputLocale, boolean isAutoCorrection, + float textFadeFactor) { final int width = mSpaceKey.mWidth; final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight; final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(buffer); final Resources res = mContext.getResources(); - canvas.drawColor(res.getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance(); // If application locales are explicitly selected. - if (subtypeSwitcher.needsToDisplayLanguage()) { + if (inputLocale != null) { final Paint paint = new Paint(); - paint.setAlpha(opacity); paint.setAntiAlias(true); paint.setTextAlign(Align.CENTER); @@ -253,7 +276,7 @@ public class LatinKeyboard extends Keyboard { } final boolean allowVariableTextSize = true; - final String language = layoutSpacebar(paint, subtypeSwitcher.getInputLocale(), + final String language = layoutSpacebar(paint, inputLocale, mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height, getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize), allowVariableTextSize); @@ -265,14 +288,16 @@ public class LatinKeyboard extends Keyboard { final float textHeight = -paint.ascent() + descent; final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE : height / 2 + textHeight / 2; - paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, mSpacebarTextFadeFactor)); + paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, textFadeFactor)); canvas.drawText(language, width / 2, baseline - descent - 1, paint); - paint.setColor(getSpacebarTextColor(mSpacebarTextColor, mSpacebarTextFadeFactor)); + paint.setColor(getSpacebarTextColor(mSpacebarTextColor, textFadeFactor)); canvas.drawText(language, width / 2, baseline - descent, paint); // Put arrows that are already layed out on either side of the text - if (subtypeSwitcher.useSpacebarLanguageSwitcher() - && subtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) { + if (mSubtypeSwitcher.useSpacebarLanguageSwitcher() + && mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) { + mButtonArrowLeftIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor)); + mButtonArrowRightIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor)); mButtonArrowLeftIcon.draw(canvas); mButtonArrowRightIcon.draw(canvas); } @@ -316,9 +341,25 @@ public class LatinKeyboard extends Keyboard { mSpaceKey.getPreviewIcon().invalidateSelf(); } + // This method is called when "popup on keypress" is off. + @Override + public boolean needSpacebarPreview(int keyIndex) { + if (!mSubtypeSwitcher.useSpacebarLanguageSwitcher()) + return false; + // Dismiss key preview. + if (keyIndex == KeyDetector.NOT_A_KEY) + return true; + // Key is not a spacebar. + if (keyIndex != mSpaceKeyIndexArray[0]) + return false; + // The language switcher will be displayed only when the dragging distance is greater + // than average key width of this keyboard. + return Math.abs(mSpaceDragLastDiff) > getMostCommonKeyWidth(); + } + public int getLanguageChangeDirection() { if (mSpaceKey == null || SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() <= 1 - || Math.abs(mSpaceDragLastDiff) < mSpaceKey.mWidth * SPACEBAR_DRAG_THRESHOLD) { + || Math.abs(mSpaceDragLastDiff) < getMostCommonKeyWidth() * SPACEBAR_DRAG_WIDTH) { return 0; // No change } return mSpaceDragLastDiff > 0 ? 1 : -1; diff --git a/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java b/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java index eee0ac61b..b279c1c7e 100644 --- a/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java +++ b/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; @@ -63,9 +64,8 @@ public class SlidingLocaleDrawable extends Drawable { mHeight = height; final TextPaint textPaint = new TextPaint(); textPaint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18)); - textPaint.setColor(android.R.color.transparent); + textPaint.setColor(Color.TRANSPARENT); textPaint.setTextAlign(Align.CENTER); - textPaint.setAlpha(LatinKeyboard.OPACITY_FULLY_OPAQUE); textPaint.setAntiAlias(true); mTextPaint = textPaint; mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;