PATTERN Cited by 1 source
Accessibility delegate override for semantic fix¶
Pattern¶
Accessibility delegate override for semantic fix is the
Android-platform pattern of correcting framework-level
accessibility semantics by attaching a subclass of
AccessibilityDelegate (or overriding the view's delegate
hook) rather than changing the underlying widget tree. The
delegate's responsibility is to rewrite what the accessibility
framework sees — element counts, roles, actions, state — so
assistive tech like TalkBack receives
semantically correct information even when the raw widget
structure contains decorative or non-semantic children.
Why the pattern exists¶
UI component libraries commonly include decorative elements
(separators, dividers, spacers, legend rows, section headers)
that are visible but not semantically list items. The Android
a11y framework defaults to reading the adapter's raw child
count into AccessibilityNodeInfoCompat.CollectionInfo, so
TalkBack announces an inflated list size. Rewriting the
widget tree to remove decoration would regress the visual
design; the delegate pattern lets the a11y semantics diverge
from the widget tree.
The same mechanism applies to a broader class of corrections: marking an element as a heading, exposing a custom role, correcting a misleading default state description, or adding custom actions (see patterns/custom-talkback-actions-as-gesture-alternative).
Canonical instance: Slack Kit SKListAccessibilityDelegate¶
From Slack's 2025-11-19 VPAT post:
Our vintage Slack Kit (SK) Bottom sheet was the primary source of the issue. SK divider, although purely decorative, was considered an item within a list. For example, if the bottom sheet had 7 row items, including 2 divider items, TalkBack would announce "7 items in a list" instead of the intended "5 items in a list".
To resolve this, we introduced a new
SKListAccessibilityDelegateforSKListAdapter, overwriting the a11yCollectionInfowith the correct number of items.
The fix lives at the component-library layer
(Slack Kit), not at each screen using
the component — which means every consumer of
SKListAdapter picks up the correct count for free.
Structure¶
- Identify the symptom — TalkBack announcing something semantically wrong (wrong count, wrong role, missing action).
- Identify the underlying framework default that produced the wrong semantics (raw adapter count, default view role, etc.).
- Subclass
AccessibilityDelegate(orRecyclerView.ItemDelegate/RecyclerViewAccessibilityDelegatevariants depending on the widget). - Override the specific hook —
onInitializeAccessibilityNodeInfo,onPopulateAccessibilityEvent,getCollectionInfo, etc. - Attach the delegate at component-library layer if the symptom is generic, not at each screen.
- Cover the fix with an automated a11y regression (Axe-in- Playwright for web; Espresso + AccessibilityChecks on Android; manual smoke with TalkBack turned on).
When this pattern is the right tool¶
- The UI correctly models visual hierarchy but the a11y framework's default semantic extraction is wrong.
- The fix should apply to every consumer of a shared component.
- Changing the widget tree would regress visual design or performance.
When to avoid¶
- If the widget tree itself is wrong (e.g. sem-level siblings with no container), fix the tree; delegate overrides propagate hacks.
- If the correction is one-off for a specific screen, inlining the delegate at that screen is fine.
- If the platform provides a first-class attribute for the
need (e.g.
android:importantForAccessibility="no"for pure decoration), prefer that over a delegate override.
Generalisation¶
The pattern generalises to any assistive-tech API where the platform provides a delegate or decorator surface for rewriting the semantic layer:
- iOS VoiceOver —
UIAccessibilityinformal protocol onUIView/UIAccessibilityContainer. - Web ARIA —
aria-*attribute overrides on DOM nodes. - Desktop —
UIAutomation(Windows), NSAccessibility (macOS) delegate protocols.
Each platform has a different surface, but the shape — rewrite the semantic layer without touching the rendering layer — is the same.
Seen in¶
- sources/2025-11-19-slack-android-vpat-journey —
canonical Android instance;
SKListAccessibilityDelegateoverridingCollectionInfoto excludeSK dividerdecorative items from TalkBack's "N items in a list" announcement.
Related¶
- systems/android-accessibility-framework — the API substrate.
- systems/talkback — the consumer of the semantic layer being rewritten.
- systems/slack-kit — the canonical component library instance.
- patterns/custom-talkback-actions-as-gesture-alternative — sibling pattern: the delegate extension point also carries custom-action additions.
- patterns/vpat-driven-a11y-triage — the workflow surfacing these bugs in the first place.