diff options
| author | 2015-03-23 11:50:46 -0700 | |
|---|---|---|
| committer | 2015-03-23 11:50:46 -0700 | |
| commit | b9bbbb1d97adb8ffdda2af14921401aabcec8cdd (patch) | |
| tree | a7ccb6ef3bb84208300dbe3519d050c71925803c | |
| parent | bf54a8af3b9abdb98b6b8398df692d65714c5141 (diff) | |
Text selection - Don't select vertical white space
This alters text selection so that you won't select a
whitespace line above or below your selection unless you select
a non-whitespace character past the line.
Change-Id: Ic93f77f6ccecb06be2acc83524ca9e9a627660ce
| -rw-r--r-- | core/java/android/widget/Editor.java | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index d93b21254e1b..253d95c55766 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3331,7 +3331,7 @@ public class Editor { // Minimum touch target size for handles private int mMinSize; // Indicates the line of text that the handle is on. - protected int mLine = -1; + protected int mPrevLine = -1; public HandleView(Drawable drawableLtr, Drawable drawableRtl) { super(mTextView.getContext()); @@ -3509,7 +3509,7 @@ public class Editor { addPositionToTouchUpFilter(offset); } final int line = layout.getLineForOffset(offset); - mLine = line; + mPrevLine = line; mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX - getHorizontalOffset() + getCursorOffset()); @@ -3858,19 +3858,22 @@ public class Editor { public void updatePosition(float x, float y) { final int trueOffset = mTextView.getOffsetForPosition(x, y); final int currLine = mTextView.getLineAtCoordinate(y); - int offset = trueOffset; - boolean positionCursor = false; + // Don't select white space on different lines. + if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return; + + boolean positionCursor = false; + int offset = trueOffset; int end = getWordEnd(offset, true); int start = getWordStart(offset); if (offset < mPrevOffset) { // User is increasing the selection. - if (!mInWord || currLine < mLine) { + if (!mInWord || currLine < mPrevLine) { // We're not in a word, or we're on a different line so we'll expand by // word. First ensure the user has at least entered the next word. int offsetToWord = Math.min((end - start) / 2, 2); - if (offset <= end - offsetToWord || currLine < mLine) { + if (offset <= end - offsetToWord || currLine < mPrevLine) { offset = start; } else { offset = mPrevOffset; @@ -3882,7 +3885,7 @@ public class Editor { positionCursor = true; } else if (offset - mTouchWordOffset > mPrevOffset) { // User is shrinking the selection. - if (currLine > mLine) { + if (currLine > mPrevLine) { // We're on a different line, so we'll snap to word boundaries. offset = end; } @@ -3897,7 +3900,7 @@ public class Editor { final int selectionEnd = mTextView.getSelectionEnd(); if (offset >= selectionEnd) { // We can't cross the handles so let's just constrain the Y value. - int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x); + int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x); if (alteredOffset >= selectionEnd) { // Can't pass the other drag handle. offset = Math.max(0, selectionEnd - 1); @@ -3962,6 +3965,10 @@ public class Editor { public void updatePosition(float x, float y) { final int trueOffset = mTextView.getOffsetForPosition(x, y); final int currLine = mTextView.getLineAtCoordinate(y); + + // Don't select white space on different lines. + if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return; + int offset = trueOffset; boolean positionCursor = false; @@ -3970,11 +3977,11 @@ public class Editor { if (offset > mPrevOffset) { // User is increasing the selection. - if (!mInWord || currLine > mLine) { + if (!mInWord || currLine > mPrevLine) { // We're not in a word, or we're on a different line so we'll expand by // word. First ensure the user has at least entered the next word. int midPoint = Math.min((end - start) / 2, 2); - if (offset >= start + midPoint || currLine > mLine) { + if (offset >= start + midPoint || currLine > mPrevLine) { offset = end; } else { offset = mPrevOffset; @@ -3986,7 +3993,7 @@ public class Editor { positionCursor = true; } else if (offset + mTouchWordOffset < mPrevOffset) { // User is shrinking the selection. - if (currLine > mLine) { + if (currLine > mPrevLine) { // We're on a different line, so we'll snap to word boundaries. offset = getWordStart(offset); } @@ -4000,7 +4007,7 @@ public class Editor { final int selectionStart = mTextView.getSelectionStart(); if (offset <= selectionStart) { // We can't cross the handles so let's just constrain the Y value. - int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x); + int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x); int length = mTextView.getText().length(); if (alteredOffset <= selectionStart) { // Can't pass the other drag handle. @@ -4029,6 +4036,36 @@ public class Editor { } /** + * Checks whether selection is happening on a different line than previous and + * if that line only contains whitespace up to the touch location. + * + * @param prevLine The previous line the selection was on. + * @param currLine The current line being selected. + * @param offset The offset in the text where the touch occurred. + * @return Whether or not it was just a white space line being selected. + */ + private boolean isWhitespaceLine(int prevLine, int currLine, int offset) { + if (prevLine == currLine) { + // Same line; don't care. + return false; + } + CharSequence text = mTextView.getText(); + if (offset == text.length()) { + // No character at the last position. + return false; + } + int lineEndOffset = mTextView.getLayout().getLineEnd(currLine); + for (int cp, i = offset; i < lineEndOffset; i += Character.charCount(cp)) { + cp = Character.codePointAt(text, i); + if (!Character.isSpaceChar(cp) && !Character.isWhitespace(cp)) { + // There are non white space chars on the line. + return false; + } + } + return true; + } + + /** * A CursorController instance can be used to control a cursor in the text. */ private interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener { @@ -4112,6 +4149,8 @@ public class Editor { private int mStartOffset = -1; // Indicates whether the user is selecting text and using the drag accelerator. private boolean mDragAcceleratorActive; + // Indicates the line of text the drag accelerator is on. + private int mPrevLine = -1; SelectionModifierCursorController() { resetTouchOffsets(); @@ -4209,6 +4248,8 @@ public class Editor { } } + // New selection, reset line. + mPrevLine = mTextView.getLineAtCoordinate(y); mDownPositionX = x; mDownPositionY = y; mGestureStayedInTapRegion = true; @@ -4265,6 +4306,13 @@ public class Editor { if (my > fingerOffset) my -= fingerOffset; offset = mTextView.getOffsetForPosition(mx, my); + int currLine = mTextView.getLineAtCoordinate(my); + + // Don't select white space on different lines. + if (isWhitespaceLine(mPrevLine, currLine, offset)) return; + + mPrevLine = currLine; + // 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. |