aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
authorTadashi G. Takaoka <takaoka@google.com>2011-04-27 14:14:45 +0900
committerTadashi G. Takaoka <takaoka@google.com>2011-05-09 19:17:39 +0900
commitff082d081f3ea18ff0b9b22126ee4a86504cf83c (patch)
treeb770b3c3025b9f0c544598e12b8437fb091a975e /java/src
parentaac2d87dcf8f199d942c61a1115746d61f181675 (diff)
downloadlatinime-ff082d081f3ea18ff0b9b22126ee4a86504cf83c.tar.gz
latinime-ff082d081f3ea18ff0b9b22126ee4a86504cf83c.tar.xz
latinime-ff082d081f3ea18ff0b9b22126ee4a86504cf83c.zip
Refactor KeyboardView and create MiniKeyboardView
Change-Id: I8d68b944762ccde05020978f20b3742eb6ab945b
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java288
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboard.java17
-rw-r--r--java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java124
-rw-r--r--java/src/com/android/inputmethod/keyboard/PopupPanel.java46
4 files changed, 289 insertions, 186 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 11476e069..08e739d5a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -35,17 +35,16 @@ import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
-import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.ViewGroup.MarginLayoutParams;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
@@ -53,7 +52,6 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.WeakHashMap;
/**
@@ -111,24 +109,18 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private boolean mInForeground;
private TextView mPreviewText;
private int mPreviewTextSizeLarge;
- private final int[] mOffsetInWindow = new int[2];
private boolean mShowKeyPreview = true;
private int mKeyPreviewDisplayedY;
private final int mDelayBeforePreview;
private final int mDelayAfterPreview;
private ViewGroup mPreviewPlacer;
+ private final int[] mCoordinates = new int[2];
// Mini keyboard
- private PopupWindow mMiniKeyboardWindow;
- private KeyboardView mMiniKeyboardView;
- private final WeakHashMap<Key, View> mMiniKeyboardCache = new WeakHashMap<Key, View>();
- private int mMiniKeyboardOriginX;
- private int mMiniKeyboardOriginY;
- private long mMiniKeyboardDisplayedTime;
- private int[] mWindowOffset;
- private final float mMiniKeyboardSlideAllowance;
- private int mMiniKeyboardTrackerId;
- private final boolean mConfigShowMiniKeyboardAtTouchedPoint;
+ private PopupWindow mPopupWindow;
+ private PopupPanel mPopupMiniKeyboardPanel;
+ private final WeakHashMap<Key, PopupPanel> mPopupPanelCache =
+ new WeakHashMap<Key, PopupPanel>();
/** Listener for {@link KeyboardActionListener}. */
private KeyboardActionListener mKeyboardActionListener;
@@ -148,7 +140,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
protected KeyDetector mKeyDetector = new KeyDetector();
// Swipe gesture detector
- private GestureDetector mGestureDetector;
+ protected GestureDetector mGestureDetector;
private final SwipeTracker mSwipeTracker = new SwipeTracker();
private final int mSwipeThreshold;
private final boolean mDisambiguateSwipe;
@@ -196,29 +188,24 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
@Override
public void handleMessage(Message msg) {
+ final PointerTracker tracker = (PointerTracker) msg.obj;
switch (msg.what) {
- case MSG_SHOW_KEY_PREVIEW:
- showKey(msg.arg1, (PointerTracker)msg.obj);
- break;
- case MSG_DISMISS_KEY_PREVIEW:
- mPreviewText.setVisibility(View.INVISIBLE);
- break;
- case MSG_REPEAT_KEY: {
- final PointerTracker tracker = (PointerTracker)msg.obj;
- tracker.onRepeatKey(msg.arg1);
- startKeyRepeatTimer(mKeyRepeatInterval, msg.arg1, tracker);
- break;
- }
- case MSG_LONGPRESS_KEY: {
- final PointerTracker tracker = (PointerTracker)msg.obj;
- openMiniKeyboardIfRequired(msg.arg1, tracker);
- break;
- }
- case MSG_LONGPRESS_SHIFT_KEY: {
- final PointerTracker tracker = (PointerTracker)msg.obj;
- onLongPressShiftKey(tracker);
- break;
- }
+ case MSG_SHOW_KEY_PREVIEW:
+ showKey(msg.arg1, tracker);
+ break;
+ case MSG_DISMISS_KEY_PREVIEW:
+ mPreviewText.setVisibility(View.INVISIBLE);
+ break;
+ case MSG_REPEAT_KEY:
+ tracker.onRepeatKey(msg.arg1);
+ startKeyRepeatTimer(mKeyRepeatInterval, msg.arg1, tracker);
+ break;
+ case MSG_LONGPRESS_KEY:
+ openMiniKeyboardIfRequired(msg.arg1, tracker);
+ break;
+ case MSG_LONGPRESS_SHIFT_KEY:
+ onLongPressShiftKey(tracker);
+ break;
}
}
@@ -390,12 +377,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mKeyLabelHorizontalPadding = (int)res.getDimension(
R.dimen.key_label_horizontal_alignment_padding);
- mMiniKeyboardWindow = new PopupWindow(context);
- mMiniKeyboardWindow.setBackgroundDrawable(null);
- mMiniKeyboardWindow.setAnimationStyle(R.style.MiniKeyboardAnimation);
- // Allow popup window to be drawn off the screen.
- mMiniKeyboardWindow.setClippingEnabled(false);
-
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(keyTextSize);
@@ -406,11 +387,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mKeyBackground.getPadding(mPadding);
mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density);
- // TODO: Refer frameworks/base/core/res/res/values/config.xml
+ // TODO: Refer to frameworks/base/core/res/res/values/config.xml
mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation);
- mMiniKeyboardSlideAllowance = res.getDimension(R.dimen.mini_keyboard_slide_allowance);
- mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean(
- R.bool.config_show_mini_keyboard_at_touched_point);
GestureDetector.SimpleOnGestureListener listener =
new GestureDetector.SimpleOnGestureListener() {
@@ -530,7 +508,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mKeyboardChanged = true;
invalidateAllKeys();
mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth());
- mMiniKeyboardCache.clear();
+ mPopupPanelCache.clear();
}
/**
@@ -694,7 +672,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
// Overlay a dark rectangle to dim the keyboard
- if (mMiniKeyboardView != null) {
+ if (mPopupMiniKeyboardPanel != null) {
mPaint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
canvas.drawRect(0, 0, width, height, mPaint);
}
@@ -947,8 +925,10 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mPreviewPlacer = placer;
}
if (placer instanceof FrameLayout) {
+ // Honeycomb or later.
placer.addView(keyPreview, new FrameLayout.LayoutParams(0, 0));
} else {
+ // Gingerbread or ealier.
placer.addView(keyPreview, new LinearLayout.LayoutParams(0, 0));
}
}
@@ -956,10 +936,11 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// TODO: Introduce minimum duration for displaying key previews
// TODO: Display up to two key previews when the user presses two keys at the same time
private void showKey(final int keyIndex, PointerTracker tracker) {
+ final TextView previewText = mPreviewText;
// If the key preview has no parent view yet, add it to the ViewGroup which can place
// key preview absolutely in SoftInputWindow.
- if (mPreviewText.getParent() == null) {
- addKeyPreview(mPreviewText);
+ if (previewText.getParent() == null) {
+ addKeyPreview(previewText);
}
final Key key = tracker.getKey(keyIndex);
@@ -968,56 +949,51 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// WindowManager.BadTokenException.
if (key == null || !mInForeground)
return;
+
+ mHandler.cancelAllDismissKeyPreviews();
+
final int keyDrawX = key.mX + key.mVisualInsetsLeft;
final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
// What we show as preview should match what we show on key top in onBufferDraw().
if (key.mLabel != null) {
// TODO Should take care of temporaryShiftLabel here.
- mPreviewText.setCompoundDrawables(null, null, null, null);
- mPreviewText.setText(adjustCase(tracker.getPreviewText(key)));
+ previewText.setCompoundDrawables(null, null, null, null);
+ previewText.setText(adjustCase(tracker.getPreviewText(key)));
if (key.mLabel.length() > 1) {
- mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyLetterSize);
- mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
+ previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyLetterSize);
+ previewText.setTypeface(Typeface.DEFAULT_BOLD);
} else {
- mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSizeLarge);
- mPreviewText.setTypeface(mKeyLetterStyle);
+ previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSizeLarge);
+ previewText.setTypeface(mKeyLetterStyle);
}
} else {
final Drawable previewIcon = key.getPreviewIcon();
- mPreviewText.setCompoundDrawables(null, null, null,
+ previewText.setCompoundDrawables(null, null, null,
previewIcon != null ? previewIcon : key.getIcon());
- mPreviewText.setText(null);
+ previewText.setText(null);
}
// Set the preview background state
- mPreviewText.getBackground().setState(
+ previewText.getBackground().setState(
key.mPopupCharacters != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
- mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+ previewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- int previewWidth = Math.max(mPreviewText.getMeasuredWidth(), keyDrawWidth
- + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
+ final int previewWidth = Math.max(previewText.getMeasuredWidth(), keyDrawWidth
+ + previewText.getPaddingLeft() + previewText.getPaddingRight());
final int previewHeight = mPreviewHeight;
- final ViewGroup.LayoutParams lp = mPreviewText.getLayoutParams();
- lp.width = previewWidth;
- lp.height = previewHeight;
-
- int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2;
- int previewY = key.mY - previewHeight + mPreviewOffset;
-
- mHandler.cancelAllDismissKeyPreviews();
- getLocationInWindow(mOffsetInWindow);
- previewX += mOffsetInWindow[0];
- previewY += mOffsetInWindow[1];
+ getLocationInWindow(mCoordinates);
+ final int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2 + mCoordinates[0];
+ final int previewY = key.mY - previewHeight + mCoordinates[1] + mPreviewOffset;
+ // Record key preview position to display mini-keyboard later at the same position
+ mKeyPreviewDisplayedY = previewY;
// Place the key preview.
// TODO: Adjust position of key previews which touch screen edges
- if (lp instanceof ViewGroup.MarginLayoutParams) {
- ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp;
- mlp.setMargins(previewX, previewY, 0, 0);
- }
- // Record key preview position to display mini-keyboard later at the same position
- mKeyPreviewDisplayedY = previewY;
- mPreviewText.setVisibility(VISIBLE);
+ final MarginLayoutParams lp = (MarginLayoutParams)previewText.getLayoutParams();
+ lp.width = previewWidth;
+ lp.height = previewHeight;
+ lp.setMargins(previewX, previewY, 0, 0);
+ previewText.setVisibility(VISIBLE);
}
/**
@@ -1044,8 +1020,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
if (key == null)
return;
mInvalidatedKey = key;
- mInvalidatedKeyRect.set(0, 0, key.mWidth, key.mHeight);
- mInvalidatedKeyRect.offset(key.mX + getPaddingLeft(), key.mY + getPaddingTop());
+ final int x = key.mX + getPaddingLeft();
+ final int y = key.mY + getPaddingTop();
+ mInvalidatedKeyRect.set(x, y, x + key.mWidth, y + key.mHeight);
mDirtyRect.union(mInvalidatedKeyRect);
onBufferDraw();
invalidate(mInvalidatedKeyRect);
@@ -1057,13 +1034,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
return false;
}
- Key parentKey = tracker.getKey(keyIndex);
+ final Key parentKey = tracker.getKey(keyIndex);
if (parentKey == null)
return false;
boolean result = onLongPress(parentKey, tracker);
if (result) {
dismissAllKeyPreviews();
- mMiniKeyboardTrackerId = tracker.mPointerId;
tracker.onLongPressed(mPointerQueue);
}
return result;
@@ -1081,13 +1057,18 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
}
- private View inflateMiniKeyboardContainer(Key parentKey) {
+ // This default implementation returns a popup mini keyboard panel.
+ // A derived class may return a language switcher popup panel, for instance.
+ protected PopupPanel onCreatePopupPanel(Key parentKey) {
+ if (parentKey.mPopupCharacters == null)
+ return null;
+
final View container = LayoutInflater.from(getContext()).inflate(mPopupLayout, null);
if (container == null)
throw new NullPointerException();
- final KeyboardView miniKeyboardView =
- (KeyboardView)container.findViewById(R.id.KeyboardView);
+ final PopupMiniKeyboardView miniKeyboardView =
+ (PopupMiniKeyboardView)container.findViewById(R.id.mini_keyboard_view);
miniKeyboardView.setOnKeyboardActionListener(new KeyboardActionListener() {
@Override
public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
@@ -1120,10 +1101,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mKeyboardActionListener.onRelease(primaryCode, withSliding);
}
});
- // Override default ProximityKeyDetector.
- miniKeyboardView.mKeyDetector = new MiniKeyboardKeyDetector(mMiniKeyboardSlideAllowance);
- // Remove gesture detector on mini-keyboard
- miniKeyboardView.mGestureDetector = null;
final Keyboard keyboard = new MiniKeyboardBuilder(this, mKeyboard.getPopupKeyboardResId(),
parentKey).build();
@@ -1132,87 +1109,39 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
- return container;
- }
-
- private static boolean isOneRowKeys(List<Key> keys) {
- if (keys.size() == 0) return false;
- final int edgeFlags = keys.get(0).mEdgeFlags;
- // HACK: The first key of mini keyboard which was inflated from xml and has multiple rows,
- // does not have both top and bottom edge flags on at the same time. On the other hand,
- // the first key of mini keyboard that was created with popupCharacters must have both top
- // and bottom edge flags on.
- // When you want to use one row mini-keyboard from xml file, make sure that the row has
- // both top and bottom edge flags set.
- return (edgeFlags & Keyboard.EDGE_TOP) != 0
- && (edgeFlags & Keyboard.EDGE_BOTTOM) != 0;
+ return miniKeyboardView;
}
/**
- * Called when a key is long pressed. By default this will open any mini keyboard associated
- * with this key through the attributes popupLayout and popupCharacters.
+ * Called when a key is long pressed. By default this will open mini keyboard associated
+ * with this key.
* @param parentKey the key that was long pressed
+ * @param tracker the pointer tracker which pressed the parent key
* @return true if the long press is handled, false otherwise. Subclasses should call the
* method on the base class if the subclass doesn't wish to handle the call.
*/
protected boolean onLongPress(Key parentKey, PointerTracker tracker) {
- if (parentKey.mPopupCharacters == null)
- return false;
-
- View container = mMiniKeyboardCache.get(parentKey);
- if (container == null) {
- container = inflateMiniKeyboardContainer(parentKey);
- mMiniKeyboardCache.put(parentKey, container);
- }
- mMiniKeyboardView = (KeyboardView)container.findViewById(R.id.KeyboardView);
- final MiniKeyboard miniKeyboard = (MiniKeyboard)mMiniKeyboardView.getKeyboard();
-
- if (mWindowOffset == null) {
- mWindowOffset = new int[2];
- getLocationInWindow(mWindowOffset);
+ PopupPanel popupPanel = mPopupPanelCache.get(parentKey);
+ if (popupPanel == null) {
+ popupPanel = onCreatePopupPanel(parentKey);
+ if (popupPanel == null)
+ return false;
+ mPopupPanelCache.put(parentKey, popupPanel);
}
- final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX()
- : parentKey.mX + parentKey.mWidth / 2;
- final int miniKeyboardX = pointX - miniKeyboard.getDefaultCoordX()
- - container.getPaddingLeft()
- + getPaddingLeft() + mWindowOffset[0];
- final int miniKeyboardY = parentKey.mY - mKeyboard.getVerticalGap()
- - (container.getMeasuredHeight() - container.getPaddingBottom())
- + getPaddingTop() + mWindowOffset[1];
- final int x = miniKeyboardX;
- final int y = mShowKeyPreview && isOneRowKeys(miniKeyboard.getKeys())
- ? mKeyPreviewDisplayedY : miniKeyboardY;
-
- mMiniKeyboardOriginX = x + container.getPaddingLeft() - mWindowOffset[0];
- mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1];
- if (miniKeyboard.setShifted(
- mKeyboard == null ? false : mKeyboard.isShiftedOrShiftLocked())) {
- mMiniKeyboardView.invalidateAllKeys();
+ if (mPopupWindow == null) {
+ mPopupWindow = new PopupWindow(getContext());
+ mPopupWindow.setBackgroundDrawable(null);
+ mPopupWindow.setAnimationStyle(R.style.PopupMiniKeyboardAnimation);
+ // Allow popup window to be drawn off the screen.
+ mPopupWindow.setClippingEnabled(false);
}
- // Mini keyboard needs no pop-up key preview displayed.
- mMiniKeyboardView.setKeyPreviewEnabled(false);
- mMiniKeyboardWindow.setContentView(container);
- mMiniKeyboardWindow.setWidth(container.getMeasuredWidth());
- mMiniKeyboardWindow.setHeight(container.getMeasuredHeight());
- mMiniKeyboardWindow.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
-
- // Inject down event on the key to mini keyboard.
- final long eventTime = SystemClock.uptimeMillis();
- mMiniKeyboardDisplayedTime = eventTime;
- final MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN,
- pointX, parentKey.mY + parentKey.mHeight / 2, eventTime);
- mMiniKeyboardView.onTouchEvent(downEvent);
- downEvent.recycle();
+ mPopupMiniKeyboardPanel = popupPanel;
+ popupPanel.showPanel(this, parentKey, tracker, mKeyPreviewDisplayedY, mPopupWindow);
invalidateAllKeys();
return true;
}
- private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) {
- return MotionEvent.obtain(mMiniKeyboardDisplayedTime, eventTime, action,
- x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0);
- }
-
private PointerTracker getPointerTracker(final int id) {
final ArrayList<PointerTracker> pointers = mPointerTrackers;
final KeyboardActionListener listener = mKeyboardActionListener;
@@ -1232,8 +1161,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
public boolean isInSlidingKeyInput() {
- if (mMiniKeyboardView != null) {
- return mMiniKeyboardView.isInSlidingKeyInput();
+ if (mPopupMiniKeyboardPanel != null) {
+ return mPopupMiniKeyboardPanel.isInSlidingKeyInput();
} else {
return mPointerQueue.isInSlidingKeyInput();
}
@@ -1264,7 +1193,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// Gesture detector must be enabled only when mini-keyboard is not on the screen and
// accessibility is not enabled.
// TODO: Reconcile gesture detection and accessibility features.
- if (mMiniKeyboardView == null && !mIsAccessibilityEnabled
+ if (mPopupMiniKeyboardPanel == null && !mIsAccessibilityEnabled
&& mGestureDetector != null && mGestureDetector.onTouchEvent(me)) {
dismissAllKeyPreviews();
mHandler.cancelKeyTimers();
@@ -1277,19 +1206,10 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final int x = (int)me.getX(index);
final int y = (int)me.getY(index);
- // Needs to be called after the gesture detector gets a turn, as it may have
- // displayed the mini keyboard
- if (mMiniKeyboardView != null) {
- final int miniKeyboardPointerIndex = me.findPointerIndex(mMiniKeyboardTrackerId);
- if (miniKeyboardPointerIndex >= 0 && miniKeyboardPointerIndex < pointerCount) {
- final int miniKeyboardX = (int)me.getX(miniKeyboardPointerIndex);
- final int miniKeyboardY = (int)me.getY(miniKeyboardPointerIndex);
- MotionEvent translated = generateMiniKeyboardMotionEvent(action,
- miniKeyboardX, miniKeyboardY, eventTime);
- mMiniKeyboardView.onTouchEvent(translated);
- translated.recycle();
- }
- return true;
+ // Needs to be called after the gesture detector gets a turn, as it may have displayed the
+ // mini keyboard
+ if (mPopupMiniKeyboardPanel != null) {
+ return mPopupMiniKeyboardPanel.onTouchEvent(me);
}
if (mHandler.isInKeyRepeat()) {
@@ -1370,7 +1290,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
dismissMiniKeyboard();
mDirtyRect.union(0, 0, getWidth(), getHeight());
- mMiniKeyboardCache.clear();
+ mPopupPanelCache.clear();
requestLayout();
}
@@ -1385,21 +1305,17 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
closing();
}
- private void dismissMiniKeyboard() {
- if (mMiniKeyboardWindow.isShowing()) {
- mMiniKeyboardWindow.dismiss();
- mMiniKeyboardView = null;
- mMiniKeyboardOriginX = 0;
- mMiniKeyboardOriginY = 0;
+ private boolean dismissMiniKeyboard() {
+ if (mPopupWindow != null && mPopupWindow.isShowing()) {
+ mPopupWindow.dismiss();
+ mPopupMiniKeyboardPanel = null;
invalidateAllKeys();
+ return true;
}
+ return false;
}
public boolean handleBack() {
- if (mMiniKeyboardWindow.isShowing()) {
- dismissMiniKeyboard();
- return true;
- }
- return false;
+ return dismissMiniKeyboard();
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index 3b1408ccf..5dde15e94 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -18,6 +18,8 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
+import java.util.List;
+
public class MiniKeyboard extends Keyboard {
private int mDefaultKeyCoordX;
@@ -32,4 +34,19 @@ public class MiniKeyboard extends Keyboard {
public int getDefaultCoordX() {
return mDefaultKeyCoordX;
}
+
+ public boolean isOneRowKeyboard() {
+ final List<Key> keys = getKeys();
+ if (keys.size() == 0) return false;
+ final int edgeFlags = keys.get(0).mEdgeFlags;
+ // HACK: The first key of mini keyboard which was inflated from xml and has multiple rows,
+ // does not have both top and bottom edge flags on at the same time. On the other hand,
+ // the first key of mini keyboard that was created with popupCharacters must have both top
+ // and bottom edge flags on.
+ // When you want to use one row mini-keyboard from xml file, make sure that the row has
+ // both top and bottom edge flags set.
+ return (edgeFlags & Keyboard.EDGE_TOP) != 0
+ && (edgeFlags & Keyboard.EDGE_BOTTOM) != 0;
+
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
new file mode 100644
index 000000000..12031f1ea
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2011 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.inputmethod.keyboard;
+
+import com.android.inputmethod.latin.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.PopupWindow;
+
+/**
+ * A view that renders a virtual {@link MiniKeyboard}. It handles rendering of keys and detecting
+ * key presses and touch movements.
+ */
+public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel {
+ private final int[] mCoordinates = new int[2];
+ private final boolean mConfigShowMiniKeyboardAtTouchedPoint;
+
+ private int mOriginX;
+ private int mOriginY;
+ private int mTrackerId;
+ private long mDownTime;
+
+ public PopupMiniKeyboardView(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.keyboardViewStyle);
+ }
+
+ public PopupMiniKeyboardView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final Resources res = context.getResources();
+ mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean(
+ R.bool.config_show_mini_keyboard_at_touched_point);
+ // Override default ProximityKeyDetector.
+ mKeyDetector = new MiniKeyboardKeyDetector(res.getDimension(
+ R.dimen.mini_keyboard_slide_allowance));
+ // Remove gesture detector on mini-keyboard
+ mGestureDetector = null;
+ setKeyPreviewEnabled(false);
+ }
+
+ @Override
+ public void setKeyPreviewEnabled(boolean previewEnabled) {
+ // Mini keyboard needs no pop-up key preview displayed.
+ super.setKeyPreviewEnabled(false);
+ }
+
+ @Override
+ public void showPanel(KeyboardView parentKeyboardView, Key parentKey,
+ PointerTracker tracker, int keyPreviewY, PopupWindow window) {
+ final View container = (View)getParent();
+ final MiniKeyboard miniKeyboard = (MiniKeyboard)getKeyboard();
+ final Keyboard parentKeyboard = parentKeyboardView.getKeyboard();
+
+ parentKeyboardView.getLocationInWindow(mCoordinates);
+ final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX()
+ : parentKey.mX + parentKey.mWidth / 2;
+ final int pointY = parentKey.mY;
+ final int miniKeyboardX = pointX - miniKeyboard.getDefaultCoordX()
+ - container.getPaddingLeft()
+ + parentKeyboardView.getPaddingLeft() + mCoordinates[0];
+ final int miniKeyboardY = pointY - parentKeyboard.getVerticalGap()
+ - (container.getMeasuredHeight() - container.getPaddingBottom())
+ + parentKeyboardView.getPaddingTop() + mCoordinates[1];
+ final int x = miniKeyboardX;
+ final int y = parentKeyboardView.isKeyPreviewEnabled() && miniKeyboard.isOneRowKeyboard()
+ ? keyPreviewY : miniKeyboardY;
+
+ if (miniKeyboard.setShifted(parentKeyboard.isShiftedOrShiftLocked())) {
+ invalidateAllKeys();
+ }
+ window.setContentView(container);
+ window.setWidth(container.getMeasuredWidth());
+ window.setHeight(container.getMeasuredHeight());
+ window.showAtLocation(parentKeyboardView, Gravity.NO_GRAVITY, x, y);
+
+ mOriginX = x + container.getPaddingLeft() - mCoordinates[0];
+ mOriginY = y + container.getPaddingTop() - mCoordinates[1];
+ mTrackerId = tracker.mPointerId;
+ mDownTime = SystemClock.uptimeMillis();
+
+ // Inject down event on the key to mini keyboard.
+ final MotionEvent downEvent = translateMotionEvent(MotionEvent.ACTION_DOWN, pointX,
+ pointY + parentKey.mHeight / 2, mDownTime);
+ onTouchEvent(downEvent);
+ downEvent.recycle();
+ }
+
+ private MotionEvent translateMotionEvent(int action, float x, float y, long eventTime) {
+ return MotionEvent.obtain(mDownTime, eventTime, action, x - mOriginX, y - mOriginY, 0);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent me) {
+ final int index = me.getActionIndex();
+ final int id = me.getPointerId(index);
+ if (id == mTrackerId) {
+ final MotionEvent translated = translateMotionEvent(me.getAction(), me.getX(index),
+ me.getY(index), me.getEventTime());
+ super.onTouchEvent(translated);
+ translated.recycle();
+ }
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/PopupPanel.java b/java/src/com/android/inputmethod/keyboard/PopupPanel.java
new file mode 100644
index 000000000..6f2b16148
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/PopupPanel.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 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.inputmethod.keyboard;
+
+import android.view.MotionEvent;
+import android.widget.PopupWindow;
+
+public interface PopupPanel {
+ /**
+ * Show popup panel.
+ * @param parentKeyboardView the parent KeyboardView that has the parent key.
+ * @param parentKey the parent key that is the source of this popup panel
+ * @param tracker the pointer tracker that pressesd the parent key
+ * @param keyPreviewY the Y-coordinate of key preview
+ * @param window PopupWindow to be used to show this popup panel
+ */
+ public void showPanel(KeyboardView parentKeyboardView, Key parentKey,
+ PointerTracker tracker, int keyPreviewY, PopupWindow window);
+
+ /**
+ * Check if the pointer is in siding key input mode.
+ * @return true if the pointer is sliding key input mode.
+ */
+ public boolean isInSlidingKeyInput();
+
+ /**
+ * The motion event handler.
+ * @param me the MotionEvent to be processed.
+ * @return true if the motion event is processed and should be consumed.
+ */
+ public boolean onTouchEvent(MotionEvent me);
+}