summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Gilles Debunne <debunne@google.com> 2011-01-17 09:16:40 -0800
committer Gilles Debunne <debunne@google.com> 2011-01-17 16:39:36 -0800
commitaa8d73bfc32eae0340ba5236f3580d88558359ab (patch)
treed6e9dfea1e20243ad293ed5397a550e70b4e548a
parent3d7a9707a58bb043147f30dc81c61deeeffeeef7 (diff)
Added a touch up filter in text selection handles.
This filters the touch up event, so that in case the handles' position is altered when the finger is lifted up, this unwanted movement is discarded. Bug 3282095 Change-Id: Ibfe8f49d979091ba49139449ecc13f47050608d9
-rw-r--r--core/java/android/widget/TextView.java96
1 files changed, 79 insertions, 17 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 623cd4180c3d..1604fde64e6d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7931,9 +7931,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
max = Math.max(0, Math.max(selStart, selEnd));
}
- ClipboardManager clipboard = (ClipboardManager)getContext()
- .getSystemService(Context.CLIPBOARD_SERVICE);
-
switch (id) {
case ID_COPY_URL:
URLSpan[] urls = ((Spanned) mText).getSpans(min, max, URLSpan.class);
@@ -8404,8 +8401,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
public void updatePosition(HandleView handle, int x, int y);
+ public void updateOffset(HandleView handle, int offset);
+
public void updatePosition();
+ public int getCurrentOffset(HandleView handle);
+
/**
* This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller
* a chance to become active and/or visible.
@@ -8422,7 +8423,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
private class PastePopupMenu implements OnClickListener {
- private PopupWindow mContainer;
+ private final PopupWindow mContainer;
private int mPositionX;
private int mPositionY;
private View mPasteView, mNoPasteView;
@@ -8521,12 +8522,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
private class HandleView extends View {
- private boolean mPositionOnTop = false;
private Drawable mDrawable;
- private PopupWindow mContainer;
+ private final PopupWindow mContainer;
private int mPositionX;
private int mPositionY;
- private CursorController mController;
+ private final CursorController mController;
private boolean mIsDragging;
private float mTouchToWindowOffsetX;
private float mTouchToWindowOffsetY;
@@ -8543,6 +8543,46 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private PastePopupMenu mPastePopupWindow;
private Runnable mLongPressCallback;
+ // Touch-up filter: number of previous positions remembered
+ private static final int HISTORY_SIZE = 5;
+ private static final int TOUCH_UP_FILTER_DELAY = 150;
+ private final long[] mPreviousOffsetsTimes = new long[HISTORY_SIZE];
+ private final int[] mPreviousOffsets = new int[HISTORY_SIZE];
+ private int mPreviousOffsetIndex = 0;
+ private int mNumberPreviousOffsets = 0;
+
+ public void startTouchUpFilter(int offset) {
+ mNumberPreviousOffsets = 0;
+ addPositionToTouchUpFilter(offset);
+ }
+
+ public void addPositionToTouchUpFilter(int offset) {
+ if (mNumberPreviousOffsets > 0 &&
+ mPreviousOffsets[mPreviousOffsetIndex] == offset) {
+ // Make sure only actual changes of position are recorded.
+ return;
+ }
+
+ mPreviousOffsetIndex = (mPreviousOffsetIndex + 1) % HISTORY_SIZE;
+ mPreviousOffsets[mPreviousOffsetIndex] = offset;
+ mPreviousOffsetsTimes[mPreviousOffsetIndex] = SystemClock.uptimeMillis();
+ mNumberPreviousOffsets++;
+ }
+
+ public void filterOnTouchUp() {
+ final long now = SystemClock.uptimeMillis();
+ int i = 0;
+ int index = 0;
+ final int iMax = Math.min(mNumberPreviousOffsets, HISTORY_SIZE);
+ while (i < iMax) {
+ index = (mPreviousOffsetIndex - i + HISTORY_SIZE) % HISTORY_SIZE;
+ if ((now - mPreviousOffsetsTimes[index]) >= TOUCH_UP_FILTER_DELAY) break;
+ i++;
+ }
+
+ mController.updateOffset(this, mPreviousOffsets[index]);
+ }
+
public static final int LEFT = 0;
public static final int CENTER = 1;
public static final int RIGHT = 2;
@@ -8738,20 +8778,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected void onDraw(Canvas c) {
mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
- if (mPositionOnTop) {
- c.save();
- c.rotate(180, (mRight - mLeft) / 2, (mBottom - mTop) / 2);
- mDrawable.draw(c);
- c.restore();
- } else {
- mDrawable.draw(c);
- }
+ mDrawable.draw(c);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
+ startTouchUpFilter(mController.getCurrentOffset(this));
mDownPositionX = ev.getRawX();
mDownPositionY = ev.getRawY();
mTouchToWindowOffsetX = mDownPositionX - mPositionX;
@@ -8808,6 +8842,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
}
+ filterOnTouchUp();
mIsDragging = false;
break;
@@ -8825,6 +8860,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
void positionAtCursor(final int offset, boolean bottom) {
+ addPositionToTouchUpFilter(offset);
final int width = mDrawable.getIntrinsicWidth();
final int height = mDrawable.getIntrinsicHeight();
final int line = mLayout.getLineForOffset(offset);
@@ -8940,12 +8976,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int offset = getHysteresisOffset(x, y, previousOffset);
if (offset != previousOffset) {
- Selection.setSelection((Spannable) mText, offset);
- updatePosition();
+ updateOffset(handle, offset);
}
hideDelayed();
}
+ public void updateOffset(HandleView handle, int offset) {
+ Selection.setSelection((Spannable) mText, offset);
+ updatePosition();
+ }
+
public void updatePosition() {
final int offset = getSelectionStart();
@@ -8959,6 +8999,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
getHandle().positionAtCursor(offset, true);
}
+ public int getCurrentOffset(HandleView handle) {
+ return getSelectionStart();
+ }
+
public boolean onTouchEvent(MotionEvent ev) {
return false;
}
@@ -9069,6 +9113,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
updatePosition();
}
+ public void updateOffset(HandleView handle, int offset) {
+ int start = getSelectionStart();
+ int end = getSelectionEnd();
+
+ if (mStartHandle == handle) {
+ start = offset;
+ } else {
+ end = offset;
+ }
+
+ Selection.setSelection((Spannable) mText, start, end);
+ updatePosition();
+ }
+
public void updatePosition() {
if (!isShowing()) {
return;
@@ -9089,6 +9147,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mEndHandle.positionAtCursor(selectionEnd, true);
}
+ public int getCurrentOffset(HandleView handle) {
+ return mStartHandle == handle ? getSelectionStart() : getSelectionEnd();
+ }
+
public boolean onTouchEvent(MotionEvent event) {
// This is done even when the View does not have focus, so that long presses can start
// selection and tap can move cursor from this tap position.