Android
Developer notes
- Snackbars and Toasts provide lightweight feedback about an operation
- They show a brief non-critical message at the bottom of the screen on mobile
- Snackbar or toast must be dynamically announced by the screen reader without moving focus to it
- Display only one at a time
- A Snackbar or toast can be timed to disappear, since the message is not critical information
- If the Snackbar persists, it should be in the swipe order for the screen reader user and tab order for the keyboard user
- All text in the Snackbar and Toast must be announced by the screen reader
- A Snackbar can contain an interactive element. Please follow the Native Button guidance for the CTA
- Toasts do not contain an interactive element
Focus
- For Jetpack Compose Snackbar, when there is an action available, the default accessibility behavior allows screen reader to dynamically read the message and the action
- Only manage focus when needed. Primarily, let the device manage default focus
- Consider how focus should be managed between child elements and their parent views
- External keyboard tab order often follows the screen reader focus, but sometimes needs focus management
-
Initial focus on a screen should land in a logical place (back button, screen title, first text field, first heading)
- Android Views
importantForAccessibility
makes the element visible to the Accessibility APIandroid:focusable
android=clickable
- Implement an
onClick( )
event handler for keyboard, as well asonTouch( )
nextFocusDown
nextFocusUp
nextFocusRight
nextFocusLeft
accessibilityTraversalBefore
(or after)- To move screen reader focus to newly revealed content:
Type_View_Focused
- To NOT move focus, but dynamically announce new content:
accessibilityLiveRegion
(set to polite or assertive) - To hide controls:
importantForAccessibility=false
- For a
ViewGroup
, setscreenReaderFocusable=true
and each inner object’s attribute to keyboard focus (focusable=false
)
- Jetpack Compose
Modifier.focusTarget()
makes the component focusableModifier.focusOrder()
needs to be used in combination with FocusRequesters to define focus orderModifier.onFocusEvent()
,Modifier.onFocusChanged()
can be used to observe the changes to focus stateFocusRequester
allows to request focus to individual elements with in a group of merged descendant views- Example: To customize the focus events
- step 1: define the focus requester prior.
val (first, second) = FocusRequester.createRefs()
- step 2: update the modifier to set the order.
modifier = Modifier.focusOrder(first) { this.down = second }
- focus order accepts following values: up, down, left, right, previous, next, start, end
- step 3: use
second.requestFocus()
to gain focus
- step 1: define the focus requester prior.
Code Example
- Jetpack Compose
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) },
content = { innerPadding ->
Button(
modifier = Modifier.padding(innerPadding),
onClick = {
// show snackbar as a suspend function
scope.launch {
snackbarHostState.showSnackbar("Snackbar Message")
}
}) {
Text(text = "Snackbar")
}
}
)