diff options
author | Gilles Debunne <debunne@google.com> | 2010-07-13 15:10:08 -0700 |
---|---|---|
committer | Gilles Debunne <debunne@google.com> | 2010-07-13 15:10:08 -0700 |
commit | d11f6e6460dcc41597e3a7f6cd3023f116f8c696 (patch) | |
tree | 7a89f6ceb9a178ceda3c4887c8cd43ed38a9f7c8 /core/java/android | |
parent | f35c96bb498ffa7b3348b4bf17e9e7475f6bb324 (diff) | |
download | frameworks_base-d11f6e6460dcc41597e3a7f6cd3023f116f8c696.zip frameworks_base-d11f6e6460dcc41597e3a7f6cd3023f116f8c696.tar.gz frameworks_base-d11f6e6460dcc41597e3a7f6cd3023f116f8c696.tar.bz2 |
Double and one and a half tap removed from TextView.
Text selection is now triggered by a long press. This behavior should be shared
across applications and is already implemented in the browser.
New UI guidelines say that double tap should be used for zooming only.
Change-Id: I9fae692cf3f6e565350f666fa3d5a86884439349
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/text/method/ArrowKeyMovementMethod.java | 266 |
1 files changed, 35 insertions, 231 deletions
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java index 55ec655..79a0c37 100644 --- a/core/java/android/text/method/ArrowKeyMovementMethod.java +++ b/core/java/android/text/method/ArrowKeyMovementMethod.java @@ -17,13 +17,11 @@ package android.text.method; import android.text.Layout; -import android.text.NoCopySpan; import android.text.Selection; import android.text.Spannable; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.widget.TextView; import android.widget.TextView.CursorController; @@ -38,13 +36,18 @@ public class ArrowKeyMovementMethod implements MovementMethod { */ protected CursorController mCursorController; + private boolean isCap(Spannable buffer) { + return ((MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || + (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0)); + } + + private boolean isAlt(Spannable buffer) { + return MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1; + } + private boolean up(TextView widget, Spannable buffer) { - boolean cap = (MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_SHIFT_ON) == 1) || - (MetaKeyKeyListener.getMetaState(buffer, - MetaKeyKeyListener.META_SELECTING) != 0); - boolean alt = MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_ALT_ON) == 1; + boolean cap = isCap(buffer); + boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { @@ -65,12 +68,8 @@ public class ArrowKeyMovementMethod implements MovementMethod { } private boolean down(TextView widget, Spannable buffer) { - boolean cap = (MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_SHIFT_ON) == 1) || - (MetaKeyKeyListener.getMetaState(buffer, - MetaKeyKeyListener.META_SELECTING) != 0); - boolean alt = MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_ALT_ON) == 1; + boolean cap = isCap(buffer); + boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { @@ -91,12 +90,8 @@ public class ArrowKeyMovementMethod implements MovementMethod { } private boolean left(TextView widget, Spannable buffer) { - boolean cap = (MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_SHIFT_ON) == 1) || - (MetaKeyKeyListener.getMetaState(buffer, - MetaKeyKeyListener.META_SELECTING) != 0); - boolean alt = MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_ALT_ON) == 1; + boolean cap = isCap(buffer); + boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { @@ -115,12 +110,8 @@ public class ArrowKeyMovementMethod implements MovementMethod { } private boolean right(TextView widget, Spannable buffer) { - boolean cap = (MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_SHIFT_ON) == 1) || - (MetaKeyKeyListener.getMetaState(buffer, - MetaKeyKeyListener.META_SELECTING) != 0); - boolean alt = MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_ALT_ON) == 1; + boolean cap = isCap(buffer); + boolean alt = isAlt(buffer); Layout layout = widget.getLayout(); if (cap) { @@ -169,10 +160,9 @@ public class ArrowKeyMovementMethod implements MovementMethod { break; case KeyEvent.KEYCODE_DPAD_CENTER: - if (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) { - if (widget.showContextMenu()) { + if ((MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) && + (widget.showContextMenu())) { handled = true; - } } } @@ -190,8 +180,7 @@ public class ArrowKeyMovementMethod implements MovementMethod { public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) { int code = event.getKeyCode(); - if (code != KeyEvent.KEYCODE_UNKNOWN - && event.getAction() == KeyEvent.ACTION_MULTIPLE) { + if (code != KeyEvent.KEYCODE_UNKNOWN && event.getAction() == KeyEvent.ACTION_MULTIPLE) { int repeat = event.getRepeatCount(); boolean handled = false; while ((--repeat) > 0) { @@ -228,54 +217,20 @@ public class ArrowKeyMovementMethod implements MovementMethod { if (widget.isFocused() && !widget.didTouchFocusSelect()) { if (event.getAction() == MotionEvent.ACTION_DOWN) { - boolean cap = (MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_SHIFT_ON) == 1) || - (MetaKeyKeyListener.getMetaState(buffer, - MetaKeyKeyListener.META_SELECTING) != 0); - int x = (int) event.getX(); - int y = (int) event.getY(); - int offset = widget.getOffset(x, y); - + boolean cap = isCap(buffer); if (cap) { - buffer.setSpan(LAST_TAP_DOWN, offset, offset, - Spannable.SPAN_POINT_POINT); + int offset = widget.getOffset((int) event.getX(), (int) event.getY()); + + buffer.setSpan(LAST_TAP_DOWN, offset, offset, Spannable.SPAN_POINT_POINT); // Disallow intercepting of the touch events, so that // users can scroll and select at the same time. // without this, users would get booted out of select // mode once the view detected it needed to scroll. widget.getParent().requestDisallowInterceptTouchEvent(true); - } else { - OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(), - OnePointFiveTapState.class); - - if (tap.length > 0) { - if (event.getEventTime() - tap[0].mWhen <= - ViewConfiguration.getDoubleTapTimeout() && - sameWord(buffer, offset, Selection.getSelectionEnd(buffer))) { - - tap[0].active = true; - MetaKeyKeyListener.startSelecting(widget, buffer); - widget.getParent().requestDisallowInterceptTouchEvent(true); - buffer.setSpan(LAST_TAP_DOWN, offset, offset, - Spannable.SPAN_POINT_POINT); - } - - tap[0].mWhen = event.getEventTime(); - } else { - OnePointFiveTapState newtap = new OnePointFiveTapState(); - newtap.mWhen = event.getEventTime(); - newtap.active = false; - buffer.setSpan(newtap, 0, buffer.length(), - Spannable.SPAN_INCLUSIVE_INCLUSIVE); - } } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - boolean cap = (MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_SHIFT_ON) == 1) || - (MetaKeyKeyListener.getMetaState(buffer, - MetaKeyKeyListener.META_SELECTING) != 0); - + boolean cap = isCap(buffer); if (cap && handled) { // Before selecting, make sure we've moved out of the "slop". @@ -289,39 +244,9 @@ public class ArrowKeyMovementMethod implements MovementMethod { // Update selection as we're moving the selection area. // Get the current touch position - int x = (int) event.getX(); - int y = (int) event.getY(); - int offset = widget.getOffset(x, y); - - final OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(), - OnePointFiveTapState.class); - - if (tap.length > 0 && tap[0].active) { - // Get the last down touch position (the position at which the - // user started the selection) - int lastDownOffset = buffer.getSpanStart(LAST_TAP_DOWN); - - // Compute the selection boundaries - int spanstart; - int spanend; - if (offset >= lastDownOffset) { - // Expand from word start of the original tap to new word - // end, since we are selecting "forwards" - spanstart = findWordStart(buffer, lastDownOffset); - spanend = findWordEnd(buffer, offset); - } else { - // Expand to from new word start to word end of the original - // tap since we are selecting "backwards". - // The spanend will always need to be associated with the touch - // up position, so that refining the selection with the - // trackball will work as expected. - spanstart = findWordEnd(buffer, lastDownOffset); - spanend = findWordStart(buffer, offset); - } - Selection.setSelection(buffer, spanstart, spanend); - } else { - Selection.extendSelection(buffer, offset); - } + int offset = widget.getOffset((int) event.getX(), (int) event.getY()); + + Selection.extendSelection(buffer, offset); return true; } } else if (event.getAction() == MotionEvent.ACTION_UP) { @@ -330,70 +255,17 @@ public class ArrowKeyMovementMethod implements MovementMethod { // the current scroll offset to avoid the scroll jumping later // to show it. if ((initialScrollY >= 0 && initialScrollY != widget.getScrollY()) || - (initialScrollX >= 0 && initialScrollX != widget.getScrollX())) { + (initialScrollX >= 0 && initialScrollX != widget.getScrollX())) { widget.moveCursorToVisibleOffset(); return true; } - int x = (int) event.getX(); - int y = (int) event.getY(); - int off = widget.getOffset(x, y); - - // XXX should do the same adjust for x as we do for the line. - - OnePointFiveTapState[] onepointfivetap = buffer.getSpans(0, buffer.length(), - OnePointFiveTapState.class); - if (onepointfivetap.length > 0 && onepointfivetap[0].active && - Selection.getSelectionStart(buffer) == Selection.getSelectionEnd(buffer)) { - // If we've set select mode, because there was a onepointfivetap, - // but there was no ensuing swipe gesture, undo the select mode - // and remove reference to the last onepointfivetap. - MetaKeyKeyListener.stopSelecting(widget, buffer); - for (int i=0; i < onepointfivetap.length; i++) { - buffer.removeSpan(onepointfivetap[i]); - } + int offset = widget.getOffset((int) event.getX(), (int) event.getY()); + if (isCap(buffer)) { buffer.removeSpan(LAST_TAP_DOWN); - } - boolean cap = (MetaKeyKeyListener.getMetaState(buffer, - KeyEvent.META_SHIFT_ON) == 1) || - (MetaKeyKeyListener.getMetaState(buffer, - MetaKeyKeyListener.META_SELECTING) != 0); - - DoubleTapState[] tap = buffer.getSpans(0, buffer.length(), - DoubleTapState.class); - boolean doubletap = false; - - if (tap.length > 0) { - if (event.getEventTime() - tap[0].mWhen <= - ViewConfiguration.getDoubleTapTimeout() && - sameWord(buffer, off, Selection.getSelectionEnd(buffer))) { - - doubletap = true; - } - - tap[0].mWhen = event.getEventTime(); + Selection.extendSelection(buffer, offset); } else { - DoubleTapState newtap = new DoubleTapState(); - newtap.mWhen = event.getEventTime(); - buffer.setSpan(newtap, 0, buffer.length(), - Spannable.SPAN_INCLUSIVE_INCLUSIVE); - } - - if (cap) { - buffer.removeSpan(LAST_TAP_DOWN); - if (onepointfivetap.length > 0 && onepointfivetap[0].active) { - // If we selecting something with the onepointfivetap-and - // swipe gesture, stop it on finger up. - MetaKeyKeyListener.stopSelecting(widget, buffer); - } else { - Selection.extendSelection(buffer, off); - } - } else if (doubletap) { - Selection.setSelection(buffer, - findWordStart(buffer, off), - findWordEnd(buffer, off)); - } else { - Selection.setSelection(buffer, off); + Selection.setSelection(buffer, offset); } MetaKeyKeyListener.adjustMetaAfterKeypress(buffer); @@ -438,75 +310,6 @@ public class ArrowKeyMovementMethod implements MovementMethod { mCursorController = cursorController; } - private static class DoubleTapState implements NoCopySpan { - long mWhen; - } - - /* We check for a onepointfive tap. This is similar to - * doubletap gesture (where a finger goes down, up, down, up, in a short - * time period), except in the onepointfive tap, a users finger only needs - * to go down, up, down in a short time period. We detect this type of tap - * to implement the onepointfivetap-and-swipe selection gesture. - * This gesture allows users to select a segment of text without going - * through the "select text" option in the context menu. - */ - private static class OnePointFiveTapState implements NoCopySpan { - long mWhen; - boolean active; - } - - private static boolean sameWord(CharSequence text, int one, int two) { - int start = findWordStart(text, one); - int end = findWordEnd(text, one); - - if (end == start) { - return false; - } - - return start == findWordStart(text, two) && - end == findWordEnd(text, two); - } - - // TODO: Unify with TextView.getWordForDictionary() - private static int findWordStart(CharSequence text, int start) { - for (; start > 0; start--) { - char c = text.charAt(start - 1); - int type = Character.getType(c); - - if (c != '\'' && - type != Character.UPPERCASE_LETTER && - type != Character.LOWERCASE_LETTER && - type != Character.TITLECASE_LETTER && - type != Character.MODIFIER_LETTER && - type != Character.DECIMAL_DIGIT_NUMBER) { - break; - } - } - - return start; - } - - // TODO: Unify with TextView.getWordForDictionary() - private static int findWordEnd(CharSequence text, int end) { - int len = text.length(); - - for (; end < len; end++) { - char c = text.charAt(end); - int type = Character.getType(c); - - if (c != '\'' && - type != Character.UPPERCASE_LETTER && - type != Character.LOWERCASE_LETTER && - type != Character.TITLECASE_LETTER && - type != Character.MODIFIER_LETTER && - type != Character.DECIMAL_DIGIT_NUMBER) { - break; - } - } - - return end; - } - public boolean canSelectArbitrarily() { return true; } @@ -543,8 +346,9 @@ public class ArrowKeyMovementMethod implements MovementMethod { } public static MovementMethod getInstance() { - if (sInstance == null) + if (sInstance == null) { sInstance = new ArrowKeyMovementMethod(); + } return sInstance; } |