Accessibility Validator (Android)
Checklist
TalkBack
- Interactive elements have
contentDescriptionvia semantics - Decorative elements:
Modifier.semantics { invisibleToUser() } - Related elements:
Modifier.semantics(mergeDescendants = true) - contentDescription is localized
- Use
Role(e.g.,Role.Button,Role.Switch,Role.Checkbox) viasemantics { role = Role.Button } - Provide
stateDescriptionfor toggles/switches (e.g., "On", "Checked") - Mark headings with
semantics { heading() } - Use
onClickLabelfor custom action descriptions - Control traversal order with
isTraversalGroupandtraversalIndexwhen default order is insufficient - Override defaults with
clearAndSetSemantics { ... }for complex custom components
Dynamic Text
- Use
spfor text sizes, notdp - Use
MaterialTheme.typographyscales - Layout adapts to large text sizes
- Support pinch-to-zoom scalable content with
Modifier.transformable+ state updates where appropriate
Color Contrast
- Text: 4.5:1 (normal), 3:1 (large 18sp+)
- Use Material Theme semantic colors
- Color not sole indicator
Touch Targets
- Minimum 48dp
- Use
Modifier.minimumInteractiveComponentSize()
Testing
- Manual testing with TalkBack enabled
- Automated checks via
enableAccessibilityChecks()in Compose tests
Quick Fixes
| Issue | Fix |
|---|---|
| No contentDescription | Modifier.semantics { contentDescription = "desc" } |
| Decorative | Modifier.semantics { invisibleToUser() } |
| Group | Modifier.semantics(mergeDescendants = true) |
| Small target | Modifier.size(48.dp) |
| Fixed font | Use MaterialTheme.typography.bodyLarge |
| Missing role or state | Modifier.semantics { role = Role.Switch; stateDescription = "On" } |
| Wrong traversal order | Modifier.semantics { isTraversalGroup = true; traversalIndex = 1 } |
Severity
- 🔴 Critical: Blocks accessibility
- 🟡 Moderate: Reduces usability
- 🟢 Minor: Enhancement