diff options
| -rw-r--r-- | core/java/android/view/AccessibilityIterators.java | 168 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 31 | ||||
| -rw-r--r-- | core/java/android/widget/AccessibilityIterators.java | 77 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 10 |
4 files changed, 128 insertions, 158 deletions
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java index cd54f249f47c..2a7dc181def1 100644 --- a/core/java/android/view/AccessibilityIterators.java +++ b/core/java/android/view/AccessibilityIterators.java @@ -47,7 +47,6 @@ public final class AccessibilityIterators { * @hide */ public static abstract class AbstractTextSegmentIterator implements TextSegmentIterator { - protected static final int DONE = -1; protected String mText; @@ -104,20 +103,20 @@ public final class AccessibilityIterators { if (offset >= textLegth) { return null; } - int start = -1; - if (offset < 0) { - offset = 0; - if (mImpl.isBoundary(offset)) { - start = offset; - } - } + int start = offset; if (start < 0) { - start = mImpl.following(offset); + start = 0; } - if (start < 0) { - return null; + while (!mImpl.isBoundary(start)) { + start = mImpl.following(start); + if (start == BreakIterator.DONE) { + return null; + } } final int end = mImpl.following(start); + if (end == BreakIterator.DONE) { + return null; + } return getRange(start, end); } @@ -130,20 +129,20 @@ public final class AccessibilityIterators { if (offset <= 0) { return null; } - int end = -1; - if (offset > mText.length()) { - offset = mText.length(); - if (mImpl.isBoundary(offset)) { - end = offset; - } + int end = offset; + if (end > textLegth) { + end = textLegth; } - if (end < 0) { - end = mImpl.preceding(offset); + while (!mImpl.isBoundary(end)) { + end = mImpl.preceding(end); + if (end == BreakIterator.DONE) { + return null; + } } - if (end < 0) { + final int start = mImpl.preceding(end); + if (start == BreakIterator.DONE) { return null; } - final int start = mImpl.preceding(end); return getRange(start, end); } @@ -195,25 +194,20 @@ public final class AccessibilityIterators { if (offset >= mText.length()) { return null; } - int start = -1; - if (offset < 0) { - offset = 0; - if (mImpl.isBoundary(offset) && isLetterOrDigit(offset)) { - start = offset; - } - } + int start = offset; if (start < 0) { - while ((offset = mImpl.following(offset)) != DONE) { - if (isLetterOrDigit(offset)) { - start = offset; - break; - } + start = 0; + } + while (!isLetterOrDigit(start) && !isStartBoundary(start)) { + start = mImpl.following(start); + if (start == BreakIterator.DONE) { + return null; } } - if (start < 0) { + final int end = mImpl.following(start); + if (end == BreakIterator.DONE || !isEndBoundary(end)) { return null; } - final int end = mImpl.following(start); return getRange(start, end); } @@ -226,28 +220,33 @@ public final class AccessibilityIterators { if (offset <= 0) { return null; } - int end = -1; - if (offset > mText.length()) { - offset = mText.length(); - if (mImpl.isBoundary(offset) && offset > 0 && isLetterOrDigit(offset - 1)) { - end = offset; - } + int end = offset; + if (end > textLegth) { + end = textLegth; } - if (end < 0) { - while ((offset = mImpl.preceding(offset)) != DONE) { - if (offset > 0 && isLetterOrDigit(offset - 1)) { - end = offset; - break; - } + while (end > 0 && !isLetterOrDigit(end - 1) && !isEndBoundary(end)) { + end = mImpl.preceding(end); + if (end == BreakIterator.DONE) { + return null; } } - if (end < 0) { + final int start = mImpl.preceding(end); + if (start == BreakIterator.DONE || !isStartBoundary(start)) { return null; } - final int start = mImpl.preceding(end); return getRange(start, end); } + private boolean isStartBoundary(int index) { + return isLetterOrDigit(index) + && (index == 0 || !isLetterOrDigit(index - 1)); + } + + private boolean isEndBoundary(int index) { + return (index > 0 && isLetterOrDigit(index - 1)) + && (index == mText.length() || !isLetterOrDigit(index)); + } + private boolean isLetterOrDigit(int index) { if (index >= 0 && index < mText.length()) { final int codePoint = mText.codePointAt(index); @@ -276,31 +275,19 @@ public final class AccessibilityIterators { if (offset >= textLength) { return null; } - int start = -1; - if (offset < 0) { - start = 0; - } else { - for (int i = offset + 1; i < textLength; i++) { - if (mText.charAt(i) == '\n') { - start = i; - break; - } - } - } + int start = offset; if (start < 0) { - return null; + start = 0; } - while (start < textLength && mText.charAt(start) == '\n') { + while (start < textLength && mText.charAt(start) == '\n' + && !isStartBoundary(start)) { start++; } - int end = start; - for (int i = end + 1; i < textLength; i++) { - end = i; - if (mText.charAt(i) == '\n') { - break; - } + if (start >= textLength) { + return null; } - while (end < textLength && mText.charAt(end) == '\n') { + int end = start + 1; + while (end < textLength && !isEndBoundary(end)) { end++; } return getRange(start, end); @@ -315,38 +302,31 @@ public final class AccessibilityIterators { if (offset <= 0) { return null; } - int end = -1; - if (offset > mText.length()) { - end = mText.length(); - } else { - if (offset > 0 && mText.charAt(offset - 1) == '\n') { - offset--; - } - for (int i = offset - 1; i >= 0; i--) { - if (i > 0 && mText.charAt(i - 1) == '\n') { - end = i; - break; - } - } + int end = offset; + if (end > textLength) { + end = textLength; + } + while(end > 0 && mText.charAt(end - 1) == '\n' && !isEndBoundary(end)) { + end--; } if (end <= 0) { return null; } - int start = end; - while (start > 0 && mText.charAt(start - 1) == '\n') { + int start = end - 1; + while (start > 0 && !isStartBoundary(start)) { start--; } - if (start == 0 && mText.charAt(start) == '\n') { - return null; - } - for (int i = start - 1; i >= 0; i--) { - start = i; - if (start > 0 && mText.charAt(i - 1) == '\n') { - break; - } - } - start = Math.max(0, start); return getRange(start, end); } + + private boolean isStartBoundary(int index) { + return (mText.charAt(index) != '\n' + && (index == 0 || mText.charAt(index - 1) == '\n')); + } + + private boolean isEndBoundary(int index) { + return (index > 0 && mText.charAt(index - 1) != '\n' + && (index == mText.length() || mText.charAt(index) == '\n')); + } } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 20eef11de8bc..49efea36b208 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1596,7 +1596,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal /** * @hide */ - private int mAccessibilityCursorPosition = -1; + private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; /** * The view's tag. @@ -2468,6 +2468,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004; /** + * The undefined cursor position. + */ + private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1; + + /** * Indicates that the screen has changed state and is now off. * * @see #onScreenStateChanged(int) @@ -6202,7 +6207,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); notifyAccessibilityStateChanged(); // Clear the text navigation state. - setAccessibilityCursorPosition(-1); + setAccessibilityCursorPosition(ACCESSIBILITY_CURSOR_POSITION_UNDEFINED); } // Clear the global reference of accessibility focus if this // view or any of its descendants had accessibility focus. @@ -6252,6 +6257,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal void clearAccessibilityFocusNoCallbacks() { if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) { mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED; + setAccessibilityCursorPosition(ACCESSIBILITY_CURSOR_POSITION_UNDEFINED); invalidate(); } } @@ -6681,12 +6687,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal final int current = getAccessibilityCursorPosition(); final int[] range = iterator.following(current); if (range == null) { - setAccessibilityCursorPosition(-1); return false; } final int start = range[0]; final int end = range[1]; - setAccessibilityCursorPosition(start); + setAccessibilityCursorPosition(end); sendViewTextTraversedAtGranularityEvent( AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, granularity, start, end); @@ -6702,16 +6707,26 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (iterator == null) { return false; } - final int selectionStart = getAccessibilityCursorPosition(); - final int current = selectionStart >= 0 ? selectionStart : text.length() + 1; + int current = getAccessibilityCursorPosition(); + if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { + current = text.length(); + } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) { + // When traversing by character we always put the cursor after the character + // to ease edit and have to compensate before asking the for previous segment. + current--; + } final int[] range = iterator.preceding(current); if (range == null) { - setAccessibilityCursorPosition(-1); return false; } final int start = range[0]; final int end = range[1]; - setAccessibilityCursorPosition(end); + // Always put the cursor after the character to ease edit. + if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) { + setAccessibilityCursorPosition(end); + } else { + setAccessibilityCursorPosition(start); + } sendViewTextTraversedAtGranularityEvent( AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, granularity, start, end); diff --git a/core/java/android/widget/AccessibilityIterators.java b/core/java/android/widget/AccessibilityIterators.java index e800e8df575f..a3d58a4e2060 100644 --- a/core/java/android/widget/AccessibilityIterators.java +++ b/core/java/android/widget/AccessibilityIterators.java @@ -56,16 +56,18 @@ final class AccessibilityIterators { if (offset >= mText.length()) { return null; } - int nextLine = -1; + int nextLine; if (offset < 0) { nextLine = mLayout.getLineForOffset(0); } else { final int currentLine = mLayout.getLineForOffset(offset); - if (currentLine < mLayout.getLineCount() - 1) { + if (getLineEdgeIndex(currentLine, DIRECTION_START) == offset) { + nextLine = currentLine; + } else { nextLine = currentLine + 1; } } - if (nextLine < 0) { + if (nextLine >= mLayout.getLineCount()) { return null; } final int start = getLineEdgeIndex(nextLine, DIRECTION_START); @@ -82,12 +84,14 @@ final class AccessibilityIterators { if (offset <= 0) { return null; } - int previousLine = -1; + int previousLine; if (offset > mText.length()) { previousLine = mLayout.getLineForOffset(mText.length()); } else { - final int currentLine = mLayout.getLineForOffset(offset - 1); - if (currentLine > 0) { + final int currentLine = mLayout.getLineForOffset(offset); + if (getLineEdgeIndex(currentLine, DIRECTION_END) + 1 == offset) { + previousLine = currentLine; + } else { previousLine = currentLine - 1; } } @@ -141,29 +145,18 @@ final class AccessibilityIterators { return null; } - final int currentLine = mLayout.getLineForOffset(offset); + final int start = Math.max(0, offset); + + final int currentLine = mLayout.getLineForOffset(start); final int currentLineTop = mLayout.getLineTop(currentLine); final int pageHeight = mTempRect.height() - mView.getTotalPaddingTop() - mView.getTotalPaddingBottom(); + final int nextPageStartY = currentLineTop + pageHeight; + final int lastLineTop = mLayout.getLineTop(mLayout.getLineCount() - 1); + final int currentPageEndLine = (nextPageStartY < lastLineTop) + ? mLayout.getLineForVertical(nextPageStartY) - 1 : mLayout.getLineCount() - 1; - final int nextPageStartLine; - final int nextPageEndLine; - if (offset < 0) { - nextPageStartLine = currentLine; - final int nextPageEndY = currentLineTop + pageHeight; - nextPageEndLine = mLayout.getLineForVertical(nextPageEndY); - } else { - final int nextPageStartY = currentLineTop + pageHeight; - nextPageStartLine = mLayout.getLineForVertical(nextPageStartY) + 1; - if (mLayout.getLineTop(nextPageStartLine) <= nextPageStartY) { - return null; - } - final int nextPageEndY = nextPageStartY + pageHeight; - nextPageEndLine = mLayout.getLineForVertical(nextPageEndY); - } - - final int start = getLineEdgeIndex(nextPageStartLine, DIRECTION_START); - final int end = getLineEdgeIndex(nextPageEndLine, DIRECTION_END) + 1; + final int end = getLineEdgeIndex(currentPageEndLine, DIRECTION_END) + 1; return getRange(start, end); } @@ -181,37 +174,17 @@ final class AccessibilityIterators { return null; } - final int currentLine = mLayout.getLineForOffset(offset); + final int end = Math.min(mText.length(), offset); + + final int currentLine = mLayout.getLineForOffset(end); final int currentLineTop = mLayout.getLineTop(currentLine); final int pageHeight = mTempRect.height() - mView.getTotalPaddingTop() - mView.getTotalPaddingBottom(); + final int previousPageEndY = currentLineTop - pageHeight; + final int currentPageStartLine = (previousPageEndY > 0) ? + mLayout.getLineForVertical(previousPageEndY) + 1 : 0; - final int previousPageStartLine; - final int previousPageEndLine; - if (offset > mText.length()) { - final int prevousPageStartY = mLayout.getHeight() - pageHeight; - if (prevousPageStartY < 0) { - return null; - } - previousPageStartLine = mLayout.getLineForVertical(prevousPageStartY); - previousPageEndLine = mLayout.getLineCount() - 1; - } else { - final int prevousPageStartY; - if (offset == mText.length()) { - prevousPageStartY = mLayout.getHeight() - 2 * pageHeight; - } else { - prevousPageStartY = currentLineTop - 2 * pageHeight; - } - if (prevousPageStartY < 0) { - return null; - } - previousPageStartLine = mLayout.getLineForVertical(prevousPageStartY); - final int previousPageEndY = prevousPageStartY + pageHeight; - previousPageEndLine = mLayout.getLineForVertical(previousPageEndY) - 1; - } - - final int start = getLineEdgeIndex(previousPageStartLine, DIRECTION_START); - final int end = getLineEdgeIndex(previousPageEndLine, DIRECTION_END) + 1; + final int start = getLineEdgeIndex(currentPageStartLine, DIRECTION_START); return getRange(start, end); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 81a44fdf09c5..1826341877f3 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8376,10 +8376,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public int getAccessibilityCursorPosition() { if (TextUtils.isEmpty(getContentDescription())) { - return getSelectionEnd(); - } else { - return super.getAccessibilityCursorPosition(); + final int selectionEnd = getSelectionEnd(); + if (selectionEnd >= 0) { + return selectionEnd; + } } + return super.getAccessibilityCursorPosition(); } /** @@ -8391,7 +8393,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return; } if (TextUtils.isEmpty(getContentDescription())) { - if (index >= 0) { + if (index >= 0 && index <= mText.length()) { Selection.setSelection((Spannable) mText, index); } else { Selection.removeSelection((Spannable) mText); |