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