summaryrefslogtreecommitdiff
path: root/core/java/android/widget/TextView.java
diff options
context:
space:
mode:
authoryingleiw <yingleiw@google.com>2021-08-20 15:51:02 -0700
committeryingleiw <yingleiw@google.com>2021-09-24 18:27:52 -0700
commitbc3dd0b7fa39286a2ff3455cc873acb518f9432f (patch)
treebed00b3d1da285cb66a2aaf639c56eaad7e9d365 /core/java/android/widget/TextView.java
parent62ddf061c570680ff0580bd9009184b475ae4db6 (diff)
Send TYPE_VIEW_TEXT_CHANGED a11y event when SuggestionSpan is added
When user types space after a word, we receive a text change event, but the suggestion span is not added to the text yet. The spell checker adds the span after the text change event is sent, but currently TextView doesn't send any notification. This change sends a TYPE_VIEW_TEXT_CHANGED event with the from and to index of the span, and beforeText which doesn't have the span and afterText which has the span. Bug: b/143378480 Test: tested with talkback. Change-Id: If16c2c578be5dcae20a9fd7014ff6fba2d487670
Diffstat (limited to 'core/java/android/widget/TextView.java')
-rw-r--r--core/java/android/widget/TextView.java52
1 files changed, 50 insertions, 2 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 69a5e3904715..3eaf852b3ac3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13822,9 +13822,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
TextView.this.handleTextChanged(buffer, start, before, after);
if (AccessibilityManager.getInstance(mContext).isEnabled()
- && (isFocused() || isSelected() && isShown())) {
+ && (isFocused() || (isSelected() && isShown()))) {
sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
- mBeforeText = null;
+ mBeforeText = TextUtils.stringOrSpannedString(mTransformed);
}
}
@@ -13852,6 +13852,54 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Log.v(LOG_TAG, "onSpanAdded s=" + s + " e=" + e + " what=" + what + ": " + buf);
}
TextView.this.spanChange(buf, what, -1, s, -1, e);
+ // Note we don't update mBeforeText here. We look for SuggestionSpans added after the
+ // text content changes.
+ if (AccessibilityManager.getInstance(mContext).isEnabled()
+ && (isFocused() || (isSelected() && isShown()))
+ && (what instanceof SuggestionSpan)) {
+ // When the user types a new word, and SuggestionSpans on the existing words will be
+ // removed and added again. We don't need to send out events for existing
+ // SuggestionSpans. Multiple spans can be placed on the range.
+ if (mBeforeText instanceof SpannedString) {
+ final SpannedString beforeSpannedString = (SpannedString) mBeforeText;
+ if ((beforeSpannedString.getSpanStart(what) == s)
+ && (beforeSpannedString.getSpanEnd(what) == e)) {
+ // Exactly same span is found.
+ return;
+ }
+ // Suggestion span couldn't be found. Try to find a suggestion span that has the
+ // same contents.
+ SuggestionSpan[] suggestionSpans = beforeSpannedString.getSpans(s, e,
+ SuggestionSpan.class);
+ for (final SuggestionSpan suggestionSpan : suggestionSpans) {
+ final int start = beforeSpannedString.getSpanStart(suggestionSpan);
+ if (start != s) {
+ continue;
+ }
+ final int end = beforeSpannedString.getSpanEnd(suggestionSpan);
+ if (end != e) {
+ continue;
+ }
+ if (equalSuggestionSpan(suggestionSpan, (SuggestionSpan) what)) {
+ return;
+ }
+ }
+ }
+ AccessibilityEvent event =
+ AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
+ event.setFromIndex(s);
+ event.setToIndex(e);
+ event.setBeforeText(mBeforeText);
+ sendAccessibilityEventUnchecked(event);
+ }
+ }
+
+ private boolean equalSuggestionSpan(SuggestionSpan span1, SuggestionSpan span2) {
+ // We compare flags because flags will determine the underline color.
+ return Arrays.equals(span1.getSuggestions(), span2.getSuggestions())
+ && Objects.equals(span1.getLocaleObject(), span2.getLocaleObject())
+ && span1.getLocale().equals(span2.getLocale())
+ && (span1.getFlags() == span2.getFlags());
}
public void onSpanRemoved(Spannable buf, Object what, int s, int e) {