Loading core/java/android/widget/Editor.java +50 −65 Original line number Original line Diff line number Diff line Loading @@ -3495,6 +3495,10 @@ public class Editor { mIdealVerticalOffset = 0.7f * handleHeight; mIdealVerticalOffset = 0.7f * handleHeight; } } public float getIdealVerticalOffset() { return mIdealVerticalOffset; } protected void updateDrawable() { protected void updateDrawable() { final int offset = getCurrentCursorOffset(); final int offset = getCurrentCursorOffset(); final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset); final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset); Loading Loading @@ -4279,6 +4283,7 @@ public class Editor { private int mStartOffset = -1; private int mStartOffset = -1; // Indicates whether the user is selecting text and using the drag accelerator. // Indicates whether the user is selecting text and using the drag accelerator. private boolean mDragAcceleratorActive; private boolean mDragAcceleratorActive; private boolean mHaventMovedEnoughToStartDrag; SelectionModifierCursorController() { SelectionModifierCursorController() { resetTouchOffsets(); resetTouchOffsets(); Loading Loading @@ -4343,19 +4348,20 @@ public class Editor { public void onTouchEvent(MotionEvent event) { public void onTouchEvent(MotionEvent event) { // This is done even when the View does not have focus, so that long presses can start // 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. // selection and tap can move cursor from this tap position. final float eventX = event.getX(); final float eventY = event.getY(); switch (event.getActionMasked()) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN: final float x = event.getX(); final float y = event.getY(); // Remember finger down position, to be able to start selection from there. // Remember finger down position, to be able to start selection from there. mMinTouchOffset = mMaxTouchOffset = mTextView.getOffsetForPosition(x, y); mMinTouchOffset = mMaxTouchOffset = mTextView.getOffsetForPosition( eventX, eventY); // Double tap detection // Double tap detection if (mGestureStayedInTapRegion) { if (mGestureStayedInTapRegion) { if (mDoubleTap) { if (mDoubleTap) { final float deltaX = x - mDownPositionX; final float deltaX = eventX - mDownPositionX; final float deltaY = y - mDownPositionY; final float deltaY = eventY - mDownPositionY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; ViewConfiguration viewConfiguration = ViewConfiguration.get( ViewConfiguration viewConfiguration = ViewConfiguration.get( Loading @@ -4363,16 +4369,17 @@ public class Editor { int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop(); int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop(); boolean stayedInArea = distanceSquared < doubleTapSlop * doubleTapSlop; boolean stayedInArea = distanceSquared < doubleTapSlop * doubleTapSlop; if (stayedInArea && isPositionOnText(x, y)) { if (stayedInArea && isPositionOnText(eventX, eventY)) { startSelectionActionModeWithSelectionAndStartDrag(); startSelectionActionModeWithSelectionAndStartDrag(); mDiscardNextActionUp = true; mDiscardNextActionUp = true; } } } } } } mDownPositionX = x; mDownPositionX = eventX; mDownPositionY = y; mDownPositionY = eventY; mGestureStayedInTapRegion = true; mGestureStayedInTapRegion = true; mHaventMovedEnoughToStartDrag = true; break; break; case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN: Loading @@ -4386,18 +4393,24 @@ public class Editor { break; break; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE: final ViewConfiguration viewConfiguration = ViewConfiguration.get( final ViewConfiguration viewConfig = ViewConfiguration.get( mTextView.getContext()); mTextView.getContext()); final int touchSlop = viewConfig.getScaledTouchSlop(); if (mGestureStayedInTapRegion) { if (mGestureStayedInTapRegion || mHaventMovedEnoughToStartDrag) { final float deltaX = event.getX() - mDownPositionX; final float deltaX = eventX - mDownPositionX; final float deltaY = event.getY() - mDownPositionY; final float deltaY = eventY - mDownPositionY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; int doubleTapTouchSlop = viewConfiguration.getScaledDoubleTapTouchSlop(); if (mGestureStayedInTapRegion) { int doubleTapTouchSlop = viewConfig.getScaledDoubleTapTouchSlop(); if (distanceSquared > doubleTapTouchSlop * doubleTapTouchSlop) { mGestureStayedInTapRegion = mGestureStayedInTapRegion = false; distanceSquared <= doubleTapTouchSlop * doubleTapTouchSlop; } if (mHaventMovedEnoughToStartDrag) { // We don't start dragging until the user has moved enough. mHaventMovedEnoughToStartDrag = distanceSquared <= touchSlop * touchSlop; } } } } Loading @@ -4407,56 +4420,28 @@ public class Editor { } } if (mStartOffset != -1) { if (mStartOffset != -1) { final int rawOffset = mTextView.getOffsetForPosition(event.getX(), if (!mHaventMovedEnoughToStartDrag) { event.getY()); // Offset the finger by the same vertical offset as the handles. This int offset = rawOffset; // improves visibility of the content being selected by shifting // the finger below the content. // We don't start "dragging" until the user is past the initial word that final float fingerOffset = (mStartHandle != null) // gets selected on long press. ? mStartHandle.getIdealVerticalOffset() int firstWordStart = getWordStart(mStartOffset); : touchSlop; int firstWordEnd = getWordEnd(mStartOffset); int offset = if (offset > firstWordEnd || offset < firstWordStart) { mTextView.getOffsetForPosition(eventX, eventY - fingerOffset); int startOffset; // Basically the goal in the below code is to have the highlight be // Snap to word boundaries. // offset so that your finger isn't covering the end point. int fingerOffset = viewConfiguration.getScaledTouchSlop(); float mx = event.getX(); float my = event.getY(); if (mx > fingerOffset) mx -= fingerOffset; if (my > fingerOffset) my -= fingerOffset; offset = mTextView.getOffsetForPosition(mx, my); // Perform the check for closeness at edge of view, if we're very close // don't adjust the offset to be in front of the finger - otherwise the // user can't select words at the edge. if (mTextView.getWidth() - fingerOffset > mx) { // We're going by word, so we need to make sure that the offset // that we get is within this, so we'll get the previous boundary. final WordIterator wordIterator = getWordIteratorWithText(); final int precedingOffset = wordIterator.preceding(offset); if (mStartOffset < offset) { if (mStartOffset < offset) { // Expanding with bottom handle, in this case the selection end // Expanding with end handle. // is before the finger. offset = getWordEnd(offset); offset = Math.max(precedingOffset - 1, 0); startOffset = getWordStart(mStartOffset); } else { // Expand with the start handle, in this case the selection // start is before the finger. if (precedingOffset == WordIterator.DONE) { offset = 0; } else { } else { offset = wordIterator.preceding(precedingOffset); // Expanding with start handle. } offset = getWordStart(offset); startOffset = getWordEnd(mStartOffset); } } } Selection.setSelection((Spannable) mTextView.getText(), if (offset == WordIterator.DONE) startOffset, offset); offset = rawOffset; // Need to adjust start offset based on direction of movement. int newStart = mStartOffset < offset ? getWordStart(mStartOffset) : getWordEnd(mStartOffset); Selection.setSelection((Spannable) mTextView.getText(), newStart, offset); } } } } break; break; Loading Loading
core/java/android/widget/Editor.java +50 −65 Original line number Original line Diff line number Diff line Loading @@ -3495,6 +3495,10 @@ public class Editor { mIdealVerticalOffset = 0.7f * handleHeight; mIdealVerticalOffset = 0.7f * handleHeight; } } public float getIdealVerticalOffset() { return mIdealVerticalOffset; } protected void updateDrawable() { protected void updateDrawable() { final int offset = getCurrentCursorOffset(); final int offset = getCurrentCursorOffset(); final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset); final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset); Loading Loading @@ -4279,6 +4283,7 @@ public class Editor { private int mStartOffset = -1; private int mStartOffset = -1; // Indicates whether the user is selecting text and using the drag accelerator. // Indicates whether the user is selecting text and using the drag accelerator. private boolean mDragAcceleratorActive; private boolean mDragAcceleratorActive; private boolean mHaventMovedEnoughToStartDrag; SelectionModifierCursorController() { SelectionModifierCursorController() { resetTouchOffsets(); resetTouchOffsets(); Loading Loading @@ -4343,19 +4348,20 @@ public class Editor { public void onTouchEvent(MotionEvent event) { public void onTouchEvent(MotionEvent event) { // This is done even when the View does not have focus, so that long presses can start // 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. // selection and tap can move cursor from this tap position. final float eventX = event.getX(); final float eventY = event.getY(); switch (event.getActionMasked()) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN: final float x = event.getX(); final float y = event.getY(); // Remember finger down position, to be able to start selection from there. // Remember finger down position, to be able to start selection from there. mMinTouchOffset = mMaxTouchOffset = mTextView.getOffsetForPosition(x, y); mMinTouchOffset = mMaxTouchOffset = mTextView.getOffsetForPosition( eventX, eventY); // Double tap detection // Double tap detection if (mGestureStayedInTapRegion) { if (mGestureStayedInTapRegion) { if (mDoubleTap) { if (mDoubleTap) { final float deltaX = x - mDownPositionX; final float deltaX = eventX - mDownPositionX; final float deltaY = y - mDownPositionY; final float deltaY = eventY - mDownPositionY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; ViewConfiguration viewConfiguration = ViewConfiguration.get( ViewConfiguration viewConfiguration = ViewConfiguration.get( Loading @@ -4363,16 +4369,17 @@ public class Editor { int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop(); int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop(); boolean stayedInArea = distanceSquared < doubleTapSlop * doubleTapSlop; boolean stayedInArea = distanceSquared < doubleTapSlop * doubleTapSlop; if (stayedInArea && isPositionOnText(x, y)) { if (stayedInArea && isPositionOnText(eventX, eventY)) { startSelectionActionModeWithSelectionAndStartDrag(); startSelectionActionModeWithSelectionAndStartDrag(); mDiscardNextActionUp = true; mDiscardNextActionUp = true; } } } } } } mDownPositionX = x; mDownPositionX = eventX; mDownPositionY = y; mDownPositionY = eventY; mGestureStayedInTapRegion = true; mGestureStayedInTapRegion = true; mHaventMovedEnoughToStartDrag = true; break; break; case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN: Loading @@ -4386,18 +4393,24 @@ public class Editor { break; break; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE: final ViewConfiguration viewConfiguration = ViewConfiguration.get( final ViewConfiguration viewConfig = ViewConfiguration.get( mTextView.getContext()); mTextView.getContext()); final int touchSlop = viewConfig.getScaledTouchSlop(); if (mGestureStayedInTapRegion) { if (mGestureStayedInTapRegion || mHaventMovedEnoughToStartDrag) { final float deltaX = event.getX() - mDownPositionX; final float deltaX = eventX - mDownPositionX; final float deltaY = event.getY() - mDownPositionY; final float deltaY = eventY - mDownPositionY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; final float distanceSquared = deltaX * deltaX + deltaY * deltaY; int doubleTapTouchSlop = viewConfiguration.getScaledDoubleTapTouchSlop(); if (mGestureStayedInTapRegion) { int doubleTapTouchSlop = viewConfig.getScaledDoubleTapTouchSlop(); if (distanceSquared > doubleTapTouchSlop * doubleTapTouchSlop) { mGestureStayedInTapRegion = mGestureStayedInTapRegion = false; distanceSquared <= doubleTapTouchSlop * doubleTapTouchSlop; } if (mHaventMovedEnoughToStartDrag) { // We don't start dragging until the user has moved enough. mHaventMovedEnoughToStartDrag = distanceSquared <= touchSlop * touchSlop; } } } } Loading @@ -4407,56 +4420,28 @@ public class Editor { } } if (mStartOffset != -1) { if (mStartOffset != -1) { final int rawOffset = mTextView.getOffsetForPosition(event.getX(), if (!mHaventMovedEnoughToStartDrag) { event.getY()); // Offset the finger by the same vertical offset as the handles. This int offset = rawOffset; // improves visibility of the content being selected by shifting // the finger below the content. // We don't start "dragging" until the user is past the initial word that final float fingerOffset = (mStartHandle != null) // gets selected on long press. ? mStartHandle.getIdealVerticalOffset() int firstWordStart = getWordStart(mStartOffset); : touchSlop; int firstWordEnd = getWordEnd(mStartOffset); int offset = if (offset > firstWordEnd || offset < firstWordStart) { mTextView.getOffsetForPosition(eventX, eventY - fingerOffset); int startOffset; // Basically the goal in the below code is to have the highlight be // Snap to word boundaries. // offset so that your finger isn't covering the end point. int fingerOffset = viewConfiguration.getScaledTouchSlop(); float mx = event.getX(); float my = event.getY(); if (mx > fingerOffset) mx -= fingerOffset; if (my > fingerOffset) my -= fingerOffset; offset = mTextView.getOffsetForPosition(mx, my); // Perform the check for closeness at edge of view, if we're very close // don't adjust the offset to be in front of the finger - otherwise the // user can't select words at the edge. if (mTextView.getWidth() - fingerOffset > mx) { // We're going by word, so we need to make sure that the offset // that we get is within this, so we'll get the previous boundary. final WordIterator wordIterator = getWordIteratorWithText(); final int precedingOffset = wordIterator.preceding(offset); if (mStartOffset < offset) { if (mStartOffset < offset) { // Expanding with bottom handle, in this case the selection end // Expanding with end handle. // is before the finger. offset = getWordEnd(offset); offset = Math.max(precedingOffset - 1, 0); startOffset = getWordStart(mStartOffset); } else { // Expand with the start handle, in this case the selection // start is before the finger. if (precedingOffset == WordIterator.DONE) { offset = 0; } else { } else { offset = wordIterator.preceding(precedingOffset); // Expanding with start handle. } offset = getWordStart(offset); startOffset = getWordEnd(mStartOffset); } } } Selection.setSelection((Spannable) mTextView.getText(), if (offset == WordIterator.DONE) startOffset, offset); offset = rawOffset; // Need to adjust start offset based on direction of movement. int newStart = mStartOffset < offset ? getWordStart(mStartOffset) : getWordEnd(mStartOffset); Selection.setSelection((Spannable) mTextView.getText(), newStart, offset); } } } } break; break; Loading