TalkBack, 5 of 10: Improve Settings item accessibility - #6161
eliotcougar wants to merge 6 commits into
Conversation
Make shared Settings rows expose one native interaction node, including disabled preferences. Use a genuine row-level switch toggle, keep the visual switch non-interactive, and localize collapsible group state in every maintained catalog.
Use one localized name-first disclosure label and clear only the redundant visible title semantics. Keep the native button role and expand/collapse action, without a separate state prefix. Update all nine locales and add device regression tests covering label uniqueness, state changes, the button role, and accessibility activation. Unit tests and Play Store debug assembly pass; both instrumentation tests pass on API 30. TalkBack audio was not tested because TalkBack is not installed on the emulator.
Keep the settings row as the sole native switch target, with observable checked state and a passive child Switch. Add localized stateDescription values in all nine supported locales; disabled controls remain disabled. With Compose UI 1.11.4, implicit toggle changes emit the CHECKED content change but not STATE_DESCRIPTION. On the tested TalkBack 17 build this updates the node without speaking its new state. Deriving stateDescription from checked state makes Compose emit the native event TalkBack expects. No custom announcement, role suppression or focus request is introduced. Add a native-event regression test for both directions on the same accessibility-focused row, disabled controls, row/child-area pointer input, Enter, Space and D-pad activation. The shared probe keeps TalkBack enabled. Validation: 57 Play Store debug unit tests passed; app and androidTest APKs assembled; SettingsToggleFeedbackTest passed on the Android 37.1 Pixel 9 Pro emulator with TalkBack 17. Speech-controller logs confirmed On and Off from state-change events without refocusing. Physical-device gestures and the full supported Android-version matrix were not tested.
|
The switch state feedback issue is still present in #6161. I tested the updated switch implementation in #6164 (Per-App Proxy), and the two switches there now behave correctly: after turning a switch on or off, TalkBack immediately reports the new state without requiring the user to leave the control and return to it. Could #6161 use the same approach/pattern as the updated #6164 implementation for its Settings switches? There is also another affected switch in the "Check for update" section: When I toggle this switch, TalkBack does not announce the new state at all. I have to move away from the switch and come back to it to hear whether it is on or off. So the desired behavior is the same as in the updated #6164 implementation: after toggling a switch, TalkBack should immediately report its new on/off state, while keeping the native switch semantics and without adding custom announcements. |
|
I retested #6161 from a clean branch based on upstream/master, including the latest commit bdfe08b. I can confirm that the Settings switches now provide immediate On/Off feedback with TalkBack, without requiring focus to leave and return to the control. I also retested the "Check pre-release versions" switch, which now behaves correctly as well. This matches the improved switch behavior I observed in #6164. My earlier report about the missing immediate state feedback was based on my previous test result and can be considered resolved. |
Keep Material minimum-size layout padding for enabled decorative switches while the parent row remains the sole toggle. Leave disabled rows and the tested localized state-description feedback unchanged. Expose collapsible Settings groups as headings without changing their name-first label or native button action. Replace the version-specific feedback comment with its semantic purpose and remove the obsolete Android-only probe harness from this focused PR.
Keep upstream resource corrections while retaining the focused Settings row semantics. The remaining feature diff is limited to the shared row component and its four localized accessibility labels.
Summary
Part 5 of the TalkBack series improves the existing shared Settings row primitives. Edit, list, menu, and switch rows expose one logical accessibility control, including when disabled. Persistence, screen-specific actions, and visible preference text remain unchanged.
Accessibility model
clickableandtoggleablemodifiers merge the title and supporting text into the row that owns the action.toggleable(value = checked, enabled = enabled, role = Role.Switch). The row owns the observable checked state and the single activation callback.Switch(onCheckedChange = null)is decoration, not a second action target. Touching the row or its trailing switch, accessibility activation, Enter, Space, and D-pad center use the row action.stateDescriptionchanges with the checked state, providing native state-change feedback without a custom announcement or moving accessibility focus.enabled = false; their label and supporting text stay grouped and the action cannot execute.stateDescription.The language chooser retains its existing native selectable radio rows. This PR does not change its selection behavior.
No direct accessibility announcements, live-region layer, focus manipulation, custom action menus, or native role suppression are introduced here. Android/TalkBack still controls role and disabled-state wording and the final spoken order.
Relevant official guidance: Compose API defaults, semantics, and merging and clearing semantics.
Known announcement-order limitation
TalkBack may read a switch row's long supporting description before its on/off state. That delays discovery of the setting's most important current information.
Traversal ordering controls the order of separate nodes, not the order of text, state, and role within a merged node. This PR does not put the description into
stateDescriptionor replace the switch's native semantics with a forced spoken sentence.A possible separately reviewed follow-up is to keep the primary switch row concise and move genuinely long explanations behind a named Info action opening a readable modal. Short descriptions could remain inline. That UI change is not implemented here.
Localization and scope
The four resources—group expanded/collapsed labels and On/Off state descriptions—are present in all nine maintained catalogs: English, Arabic, Bengali, Bakhtiari, Persian, Russian, Vietnamese, Simplified Chinese, and Traditional Chinese. App-provided labels use the app locale; native role and disabled wording are supplied by Android/TalkBack.
Production changes are confined to
SettingsItem.ktand these resource entries. All existing callers benefit without screen-specific callbacks, business-logic changes, or additional state holders. Notification/live-region work and the other focused list PRs remain independent.Review refinements
Commit
39637fafcadds the following refinements:Validation at
39637fafc:app:testPlaystoreDebugUnitTest: 57 tests passed, zero failures, errors, or skips.:app:compilePlaystoreDebugKotlinand:app:assemblePlaystoreDebug: passed.git diff --checkpassed.git merge-treechecks against all nine companion branches passed in both orders and produced identical trees. This commit also merges cleanly with fetchedupstream/master.Not run: audio-level verification of the exact spoken phrase/order, a physical-device repeat, older Android versions, and the full light/dark, dynamic-color, single/two-column shared-consumer rendering matrix. The emulator evidence above verifies native nodes, events, focus, and activation; it is not a claim about every TalkBack voice or device.