Repository navigation
Keep the Text accessibility delegate when the text has no links - #59521
Open
hryhoriiK97 wants to merge 1 commit into
Open
hryhoriiK97 wants to merge 1 commit into
hryhoriiK97 wants to merge 1 commit into
Conversation
Every Text update reset the accessibility delegate, creating a new ExploreByTouchHelper even when TalkBack is off and the text has no links. Keep the existing delegate when the text has no links before or after the update, and make an "auto" view important as setting the delegate does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Visual regressionNo visual differences at android: no baseline for this environment ios: no capture |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
On Android, every Text update goes through
updateExtraDatain the Text view manager (PreparedLayoutTextViewManager, andReactTextViewManagerfor the older text view). There, the text's clickable spans are stored in a view tag and the accessibility delegate is reset, so that TalkBack can reach the links.Current behavior. The comment says this is for a text view that "contains any clickable spans", but
PreparedLayoutTextViewManagerchecksis Spanned, which is true for every Text, andReactTextViewManagerhas no check at all. So every update of every Text creates a newReactTextViewAccessibilityDelegate, even when TalkBack is off and the text has no links. Creating one is anExploreByTouchHelper: it looks up theAccessibilityManager, makes the view focusable and then restores it, and allocates aHandlerand a map. When the text has no links, nothing changes for the delegate, since it reads the links only when it's created.With this change. Both managers call a new
ReactTextViewAccessibilityDelegate.updateAccessibilityLinks. When the view already has aReactTextViewAccessibilityDelegateand the text has no links, before or after the update, it keeps that delegate. In every other case (the first update, links added, changed or removed, or another delegate on the view) it resets the delegate as before. A plain Text still gets the delegate on its first update;PreparedLayoutTextViewneeds it to expose its text to TalkBack.Setting a delegate through
ViewCompatalso makes a view whoseimportantForAccessibilityisautoimportant. The kept path does the same, so a Text set back toauto(by the prop, or by view recycling) still ends up important, as before. The one difference: the accessibility actions a delegate caches from theaccessibilityActionsprop now stay between text updates, as they already do for every other view, instead of being dropped with the old delegate.Changelog:
[ANDROID] [CHANGED] - Text updates keep the accessibility delegate when the text has no links
Test Plan:
--dry-run --set-exit-if-changed) passes on all changed files.ReactTextViewAccessibilityDelegateTest(4 Robolectric tests: the first update installs the text delegate; updates without links keep the same delegate; adding and removing links resets it; a view set back toautois important after an update). With the old code only "updates without links keep the delegate" fails.PreparedLayoutTextViewAccessibilityTextTestandReactTextViewPropertyTeststill pass.assembleRelease, arm64-v8a) and compiled withcmd package compile -m speed. The scenarios are a local Playground screen, not part of this PR: 200 numbers that change every 100 ms, and 60 lines of mixed-script text (emoji, CJK, Arabic, Hebrew, Polish) that change every 100 ms.adb shell setprop, not part of this PR) that runs either the old reset on every update or this change. Launches alternate A B B A A B B A, 4 per arm and scenario; 15 s Perfetto traces with the app's trace sections. The changes are medians.updateExtraDataper call, numbersupdateExtraDataper call, mixed scriptsThese times include the cost of the trace sections themselves, about half of
updateExtraData's samples in a sampled profile, so without tracing the relative gain is larger.uiautomator dumpofTextExample,AccessibilityExampleandAccessibilityAndroidExample, 4 scroll positions each, with the old and the new code: the same 166 nodes, with the same text, content description and focusable, clickable and important-for-accessibility flags (positions differ only by the scroll). I couldn't run TalkBack on the device I used.🤖 Generated with Claude Code