Support sliding pop-up mini-keyboard input

TODO:
- Remove close button on mini-keyboard
- Dismiss mini-keyboard when finger leave the screen while no key is selected

This change also renames some instance variables to have more meaningful name.

Bug: 2959169
Change-Id: I9fd79116a647d7be82415c6e9e7cdaf6edcb2bf6
main
Tadashi G. Takaoka 2010-09-03 00:48:16 +09:00
parent f0fd506520
commit 07221a4ad1
2 changed files with 74 additions and 30 deletions

View File

@ -185,17 +185,20 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
private boolean mShowTouchPoints = true; private boolean mShowTouchPoints = true;
private int mPopupPreviewX; private int mPopupPreviewX;
private int mPopupPreviewY; private int mPopupPreviewY;
private int mPopupPreviewOffsetX;
private int mPopupPreviewOffsetY;
private int mWindowY; private int mWindowY;
// Popup mini keyboard // Popup mini keyboard
private PopupWindow mPopupKeyboard; private PopupWindow mMiniKeyboardPopup;
private View mMiniKeyboardContainer; private View mMiniKeyboardContainer;
private LatinKeyboardBaseView mMiniKeyboard; private LatinKeyboardBaseView mMiniKeyboard;
private boolean mMiniKeyboardOnScreen; private boolean mMiniKeyboardOnScreen;
private View mPopupParent; private View mMiniKeyboardParent;
private int mMiniKeyboardOffsetX;
private int mMiniKeyboardOffsetY;
private Map<Key,View> mMiniKeyboardCache; private Map<Key,View> mMiniKeyboardCache;
private int mMiniKeyboardOriginX;
private int mMiniKeyboardOriginY;
private long mMiniKeyboardPopupTime;
private int[] mWindowOffset; private int[] mWindowOffset;
/** Listener for {@link OnKeyboardActionListener}. */ /** Listener for {@link OnKeyboardActionListener}. */
@ -445,10 +448,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
mShowPreview = false; mShowPreview = false;
} }
mPreviewPopup.setTouchable(false); mPreviewPopup.setTouchable(false);
mPopupParent = this; mMiniKeyboardParent = this;
mPopupKeyboard = new PopupWindow(context); mMiniKeyboardPopup = new PopupWindow(context);
mPopupKeyboard.setBackgroundDrawable(null); mMiniKeyboardPopup.setBackgroundDrawable(null);
mPaint = new Paint(); mPaint = new Paint();
mPaint.setAntiAlias(true); mPaint.setAntiAlias(true);
@ -615,12 +618,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
} }
public void setPopupParent(View v) { public void setPopupParent(View v) {
mPopupParent = v; mMiniKeyboardParent = v;
} }
public void setPopupOffset(int x, int y) { public void setPopupOffset(int x, int y) {
mMiniKeyboardOffsetX = x; mPopupPreviewOffsetX = x;
mMiniKeyboardOffsetY = y; mPopupPreviewOffsetY = y;
if (mPreviewPopup.isShowing()) { if (mPreviewPopup.isShowing()) {
mPreviewPopup.dismiss(); mPreviewPopup.dismiss();
} }
@ -896,8 +899,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
if (mOffsetInWindow == null) { if (mOffsetInWindow == null) {
mOffsetInWindow = new int[2]; mOffsetInWindow = new int[2];
getLocationInWindow(mOffsetInWindow); getLocationInWindow(mOffsetInWindow);
mOffsetInWindow[0] += mMiniKeyboardOffsetX; // Offset may be zero mOffsetInWindow[0] += mPopupPreviewOffsetX; // Offset may be zero
mOffsetInWindow[1] += mMiniKeyboardOffsetY; // Offset may be zero mOffsetInWindow[1] += mPopupPreviewOffsetY; // Offset may be zero
int[] mWindowLocation = new int[2]; int[] mWindowLocation = new int[2];
getLocationOnScreen(mWindowLocation); getLocationOnScreen(mWindowLocation);
mWindowY = mWindowLocation[1]; mWindowY = mWindowLocation[1];
@ -926,7 +929,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
} else { } else {
previewPopup.setWidth(popupWidth); previewPopup.setWidth(popupWidth);
previewPopup.setHeight(popupHeight); previewPopup.setHeight(popupHeight);
previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY, previewPopup.showAtLocation(mMiniKeyboardParent, Gravity.NO_GRAVITY,
mPopupPreviewX, mPopupPreviewY); mPopupPreviewX, mPopupPreviewY);
} }
mPreviewText.setVisibility(VISIBLE); mPreviewText.setVisibility(VISIBLE);
@ -974,6 +977,13 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
boolean result = onLongPress(popupKey); boolean result = onLongPress(popupKey);
if (result) { if (result) {
dismissKeyPreview(); dismissKeyPreview();
long eventTime = tracker.getDownTime();
mMiniKeyboardPopupTime = eventTime;
MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN,
tracker.getLastX(), tracker.getLastY(), eventTime);
mMiniKeyboard.onTouchEvent(downEvent);
downEvent.recycle();
} }
return result; return result;
} }
@ -1020,7 +1030,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
mKeyboardActionListener.onRelease(primaryCode); mKeyboardActionListener.onRelease(primaryCode);
} }
}); });
//mInputView.setSuggest(mSuggest);
Keyboard keyboard; Keyboard keyboard;
if (popupKey.popupCharacters != null) { if (popupKey.popupCharacters != null) {
keyboard = new Keyboard(getContext(), popupKeyboardId, keyboard = new Keyboard(getContext(), popupKeyboardId,
@ -1043,20 +1053,25 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
mWindowOffset = new int[2]; mWindowOffset = new int[2];
getLocationInWindow(mWindowOffset); getLocationInWindow(mWindowOffset);
} }
int popupX = popupKey.x + getPaddingLeft(); int popupX = popupKey.x + popupKey.width + getPaddingLeft();
int popupY = popupKey.y + getPaddingTop(); int popupY = popupKey.y + getPaddingTop();
popupX = popupX + popupKey.width - mMiniKeyboardContainer.getMeasuredWidth(); popupX -= mMiniKeyboardContainer.getMeasuredWidth();
popupY = popupY - mMiniKeyboardContainer.getMeasuredHeight(); popupY -= mMiniKeyboardContainer.getMeasuredHeight();
final int x = popupX + mMiniKeyboardContainer.getPaddingRight() + mWindowOffset[0]; popupX += mWindowOffset[0];
final int y = popupY + mMiniKeyboardContainer.getPaddingBottom() + mWindowOffset[1]; popupY += mWindowOffset[1];
mMiniKeyboard.setPopupOffset(x < 0 ? 0 : x, y); final int x = popupX + mMiniKeyboardContainer.getPaddingRight();
final int y = popupY + mMiniKeyboardContainer.getPaddingBottom();
mMiniKeyboardOriginX = (x < 0 ? 0 : x) + mMiniKeyboardContainer.getPaddingLeft();
mMiniKeyboardOriginY = y + mMiniKeyboardContainer.getPaddingTop();
mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y);
mMiniKeyboard.setShifted(isShifted()); mMiniKeyboard.setShifted(isShifted());
mPopupKeyboard.setContentView(mMiniKeyboardContainer); mMiniKeyboardPopup.setContentView(mMiniKeyboardContainer);
mPopupKeyboard.setWidth(mMiniKeyboardContainer.getMeasuredWidth()); mMiniKeyboardPopup.setWidth(mMiniKeyboardContainer.getMeasuredWidth());
mPopupKeyboard.setHeight(mMiniKeyboardContainer.getMeasuredHeight()); mMiniKeyboardPopup.setHeight(mMiniKeyboardContainer.getMeasuredHeight());
mPopupKeyboard.showAtLocation(this, Gravity.NO_GRAVITY, x, y); mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
mMiniKeyboardOnScreen = true; mMiniKeyboardOnScreen = true;
//mMiniKeyboard.onTouchEvent(getTranslatedEvent(me));
// TODO: down event?
invalidateAllKeys(); invalidateAllKeys();
return true; return true;
} }
@ -1068,6 +1083,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
return mMiniKeyboardOnScreen; return mMiniKeyboardOnScreen;
} }
private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) {
return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action,
x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0);
}
private PointerTracker getPointerTracker(final int id) { private PointerTracker getPointerTracker(final int id) {
final ArrayList<PointerTracker> pointers = mPointerTrackers; final ArrayList<PointerTracker> pointers = mPointerTrackers;
final Key[] keys = mKeys; final Key[] keys = mKeys;
@ -1105,7 +1125,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
// Needs to be called after the gesture detector gets a turn, as it may have // Needs to be called after the gesture detector gets a turn, as it may have
// displayed the mini keyboard // displayed the mini keyboard
if (mMiniKeyboardOnScreen && action != MotionEvent.ACTION_CANCEL) { if (mMiniKeyboardOnScreen) {
MotionEvent translated = generateMiniKeyboardMotionEvent(action, (int)me.getX(),
(int)me.getY(), eventTime);
mMiniKeyboard.onTouchEvent(translated);
translated.recycle();
return true; return true;
} }
@ -1209,15 +1233,17 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
} }
public void dismissPopupKeyboard() { public void dismissPopupKeyboard() {
if (mPopupKeyboard.isShowing()) { if (mMiniKeyboardPopup.isShowing()) {
mPopupKeyboard.dismiss(); mMiniKeyboardPopup.dismiss();
mMiniKeyboardOnScreen = false; mMiniKeyboardOnScreen = false;
mMiniKeyboardOriginX = 0;
mMiniKeyboardOriginY = 0;
invalidateAllKeys(); invalidateAllKeys();
} }
} }
public boolean handleBack() { public boolean handleBack() {
if (mPopupKeyboard.isShowing()) { if (mMiniKeyboardPopup.isShowing()) {
dismissPopupKeyboard(); dismissPopupKeyboard();
return true; return true;
} }

View File

@ -61,6 +61,7 @@ public class PointerTracker {
private int mCurrentKey = NOT_A_KEY; private int mCurrentKey = NOT_A_KEY;
private int mStartX; private int mStartX;
private int mStartY; private int mStartY;
private long mDownTime;
// for move de-bouncing // for move de-bouncing
private int mLastCodeX; private int mLastCodeX;
@ -144,6 +145,7 @@ public class PointerTracker {
mCurrentKey = keyIndex; mCurrentKey = keyIndex;
mStartX = x; mStartX = x;
mStartY = y; mStartY = y;
mDownTime = eventTime;
startMoveDebouncing(x, y); startMoveDebouncing(x, y);
startTimeDebouncing(eventTime); startTimeDebouncing(eventTime);
checkMultiTap(eventTime, keyIndex); checkMultiTap(eventTime, keyIndex);
@ -181,7 +183,19 @@ public class PointerTracker {
mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this); mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this);
} }
} else { } else {
mHandler.cancelLongPressTimer(); if (mCurrentKey != NOT_A_KEY) {
updateTimeDebouncing(eventTime);
mCurrentKey = keyIndex;
mHandler.cancelLongPressTimer();
} else if (isMinorMoveBounce(x, y, keyIndex, mCurrentKey)) {
updateTimeDebouncing(eventTime);
} else {
resetMultiTap();
resetTimeDebouncing(eventTime, mCurrentKey);
resetMoveDebouncing();
mCurrentKey = keyIndex;
mHandler.cancelLongPressTimer();
}
} }
/* /*
* While time debouncing is in effect, mCurrentKey holds the new key and this tracker * While time debouncing is in effect, mCurrentKey holds the new key and this tracker
@ -252,6 +266,10 @@ public class PointerTracker {
return mLastY; return mLastY;
} }
public long getDownTime() {
return mDownTime;
}
// These package scope methods are only for debugging purpose. // These package scope methods are only for debugging purpose.
/* package */ int getStartX() { /* package */ int getStartX() {
return mStartX; return mStartX;