Skip to content

Stop routing TalkBack's click to removed accessibility actions on Android - #59076

Open
YevheniiKotyrlo wants to merge 2 commits into
react:mainfrom
YevheniiKotyrlo:fix/android-removed-accessibility-actions
Open

YevheniiKotyrlo wants to merge 2 commits into
react:mainfrom
YevheniiKotyrlo:fix/android-removed-accessibility-actions

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

A view that declared an activate action keeps taking TalkBack's click after its accessibilityActions are removed or replaced with []: the double-tap dispatches onAccessibilityAction with activate, and the view's own click, such as a Pressable's onPress, never runs. Two places keep the removed action. BaseViewManager.setAccessibilityActions returns before writing the tag when the prop is null, so the previous array stays on the view, and ReactAccessibilityDelegate.performAccessibilityAction routes through accessibilityActionsMap, which records every action it built node info with and forgets them only when the view is recycled.

This writes the null through, and the delegate resolves an incoming action against the view's current accessibilityActions instead of the map, so a declared action is routed as before and a removed one falls through to the view's own handling. Without the map, prepareToRecycle() (#59047) has nothing to clear, so it goes too: prepareToRecycleView already resets the actions tag the delegate now reads.

Changelog:

[ANDROID] [FIXED] - Removing or emptying accessibilityActions no longer leaves TalkBack's click on the removed action

Test Plan:

New cases in BaseViewManagerTest set accessibilityActions through the view manager, build the node info as TalkBack does, and perform an accessibility click. Before the change four fail: the click is not performed after the activate action is removed, after the actions are replaced with [], nor after activate is removed while longpress stays (expected:<[1]> but was:<[0]>), and a removed custom action is still in the node info. A declared activate takes the click with and without the change. With it, ./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest -PenableWarningsAsErrors=true passes for BaseViewManagerTest, ReactAccessibilityDelegateTest and ReactTextViewPropertyTest (54 tests), testRecycledViewPerformsItsOwnAccessibilityClick among them; the rest of build_android was not run.

RNTester with TalkBack on an Android 16 emulator, before and after: after a button's activate action is removed, the double-tap dispatches onAccessibilityAction without the change, and runs onPress with it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 14, 2026
@YevheniiKotyrlo

Copy link
Copy Markdown
Contributor Author

Device evidence — before / after

UNFIXED — after the button's activate action is removed, TalkBack's double-tap dispatches onAccessibilityAction and onPress never runs.

FIXED — the same double-tap runs onPress, and no accessibility action is dispatched.

before — main after — with this PR

RNTester debug builds of main (892ea5e45d) and of this branch, on an Android 16 (API 36) emulator at 1140×2400, density 480, with TalkBack. The scene is a Pressable with accessibilityActions={[{name: 'activate'}]} and counters for onPress and onAccessibilityAction: TalkBack focuses it, its actions are removed, and TalkBack's double-tap activates it.

@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as ready for review October 14, 2026 14:12
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 14, 2026
@YevheniiKotyrlo
YevheniiKotyrlo force-pushed the fix/android-removed-accessibility-actions branch from c9b7c00 to 2e2da47 Compare October 16, 2026 10:12
@YevheniiKotyrlo
YevheniiKotyrlo force-pushed the fix/android-removed-accessibility-actions branch from 2e2da47 to 3e0726b Compare November 11, 2026 14:42
@YevheniiKotyrlo

Copy link
Copy Markdown
Contributor Author

@javache, without this change TalkBack's double-tap on a view whose activate action was removed, or whose accessibilityActions were emptied, still dispatches onAccessibilityAction, so a Pressable's onPress never runs.

@javache
javache requested a review from cortinico November 13, 2026 10:52

@cortinico cortinico left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good, but build_fantom_runner and test_react_common_cxx are failing. Can we fix it?

…roid

A view whose accessibilityActions declared activate kept dispatching it
on TalkBack's click after the actions were removed or replaced with an
empty list, so the view's own click never ran.
setAccessibilityActions returned before writing the tag when the prop
was null, and ReactAccessibilityDelegate routed an action through a map
of every action it had built node info with, which only recycling
cleared.

setAccessibilityActions now writes null to the tag, and the delegate
resolves an action against the view's current accessibilityActions.
The map goes, and prepareToRecycle with it: recycling already resets
the actions tag the delegate now reads.
@YevheniiKotyrlo
YevheniiKotyrlo force-pushed the fix/android-removed-accessibility-actions branch from 3e0726b to c74031a Compare November 13, 2026 17:08
@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Visual regression

No visual differences at ffb8318e1745.

ios: no capture

The click reaches the view once activate is removed and longpress
stays declared, so the delegate's lookup also runs over a list that
holds no action for it.
@YevheniiKotyrlo

Copy link
Copy Markdown
Contributor Author

Both failed before building anything: the runner couldn't resolve archive.ubuntu.com in apt update (build_fantom_runner, test_react_common_cxx). They pass on a rerun of the same tree (build_fantom_runner, test_react_common_cxx).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants