From 70a6312f09329bd0b19343bc7906f9ce665fe3ad Mon Sep 17 00:00:00 2001 From: Gilles Debunne Date: Thu, 1 Sep 2011 13:27:33 -0700 Subject: [PATCH] Fixes around text selection Text selection mode was started by two consecutive taps inside a field with selectAllOnFocus. ArrowKeyMovementMethod does not respect the possible cancelLongPress and handles up events. As a result a scroll that happens to end up at its initial position will be considered a tap and will move the cursor. This is however not considered as a tap in TextView and a possible selection mode would not be stopped in that case. Fixed by making ArrowKeyMovementMethod aware of the cancel that happened in Touch. Change-Id: I07372b703f250e1edc7ee0665318ce30441b9187 --- .../text/method/ArrowKeyMovementMethod.java | 9 ++-- core/java/android/text/method/Touch.java | 9 ++-- core/java/android/widget/TextView.java | 42 +++++++++++-------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java index fe965651f70e5..b8728ee30d22b 100644 --- a/core/java/android/text/method/ArrowKeyMovementMethod.java +++ b/core/java/android/text/method/ArrowKeyMovementMethod.java @@ -232,8 +232,7 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme if (widget.isFocused() && !widget.didTouchFocusSelect()) { if (action == MotionEvent.ACTION_DOWN) { - boolean cap = isSelecting(buffer); - if (cap) { + if (isSelecting(buffer)) { int offset = widget.getOffsetForPosition(event.getX(), event.getY()); buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); @@ -245,9 +244,7 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme widget.getParent().requestDisallowInterceptTouchEvent(true); } } else if (action == MotionEvent.ACTION_MOVE) { - boolean cap = isSelecting(buffer); - - if (cap && handled) { + if (isSelecting(buffer) && handled) { // Before selecting, make sure we've moved out of the "slop". // handled will be true, if we're in select mode AND we're // OUT of the slop @@ -279,7 +276,7 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme if (isSelecting(buffer)) { buffer.removeSpan(LAST_TAP_DOWN); Selection.extendSelection(buffer, offset); - } else { + } else if (!widget.shouldIgnoreActionUpEvent()) { Selection.setSelection(buffer, offset); } diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java index a528044ef1fd4..3f9b94563a0b6 100644 --- a/core/java/android/text/method/Touch.java +++ b/core/java/android/text/method/Touch.java @@ -147,12 +147,10 @@ public class Touch { int nx = widget.getScrollX() + (int) dx; int ny = widget.getScrollY() + (int) dy; - int padding = widget.getTotalPaddingTop() + - widget.getTotalPaddingBottom(); + int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); Layout layout = widget.getLayout(); - ny = Math.min(ny, layout.getHeight() - (widget.getHeight() - - padding)); + ny = Math.min(ny, layout.getHeight() - (widget.getHeight() - padding)); ny = Math.max(ny, 0); int oldX = widget.getScrollX(); @@ -161,8 +159,7 @@ public class Touch { scrollTo(widget, layout, nx, ny); // If we actually scrolled, then cancel the up action. - if (oldX != widget.getScrollX() - || oldY != widget.getScrollY()) { + if (oldX != widget.getScrollX() || oldY != widget.getScrollY()) { widget.cancelLongPress(); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 1aa009b70e409..a5605c70a55eb 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8243,10 +8243,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return superResult; } - final boolean touchIsFinished = action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && - isFocused(); + final boolean touchIsFinished = (action == MotionEvent.ACTION_UP) && + !shouldIgnoreActionUpEvent() && isFocused(); - if ((mMovement != null || onCheckIsTextEditor()) && isEnabled() + if ((mMovement != null || onCheckIsTextEditor()) && isEnabled() && mText instanceof Spannable && mLayout != null) { boolean handled = false; @@ -8254,9 +8254,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener handled |= mMovement.onTouchEvent(this, (Spannable) mText, event); } - if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable && touchIsFinished) { + if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable) { // The LinkMovementMethod which should handle taps on links has not been installed - // to support text selection. We reproduce its behavior here to open links. + // on non editable text that support text selection. + // We reproduce its behavior here to open links for these. ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(), getSelectionEnd(), ClickableSpan.class); @@ -8266,7 +8267,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - if ((isTextEditable() || mTextIsSelectable) && touchIsFinished) { + if (touchIsFinished && (isTextEditable() || mTextIsSelectable)) { // Show the IME, except when selecting in read-only text. final InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) { @@ -8277,16 +8278,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect(); - if (!selectAllGotFocus && hasSelection()) { - startSelectionActionMode(); - } else { - hideControllers(); - if (!selectAllGotFocus && mText.length() > 0) { - if (isCursorInsideEasyCorrectionSpan()) { - showSuggestions(); - } else if (hasInsertionController()) { - getInsertionController().show(); - } + hideControllers(); + if (!selectAllGotFocus && mText.length() > 0) { + if (isCursorInsideEasyCorrectionSpan()) { + showSuggestions(); + } else if (hasInsertionController()) { + getInsertionController().show(); } } @@ -8398,7 +8395,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener super.cancelLongPress(); mIgnoreActionUpEvent = true; } - + + /** + * This method is only valid during a touch event. + * + * @return true when the ACTION_UP event should be ignored, false otherwise. + * + * @hide + */ + public boolean shouldIgnoreActionUpEvent() { + return mIgnoreActionUpEvent; + } + @Override public boolean onTrackballEvent(MotionEvent event) { if (mMovement != null && mText instanceof Spannable &&