Building Custom Components
When building custom components, checking that they work with different assistive technologies is essential. Otherwise, the app might be partly or entirely unusable for some users.
This page introduces some points to consider when developing custom components. These are the ones mentioned in the checklist - however, I will probably add more in the future. If you're interested in code samples, Appt.org has "Accessibility code samples"-repository, which contains code samples for Android, in addition to other frameworks. Most of the code samples are for Views, but they're adding samples Jetpack Compose too.
Semantics
When building custom components, you must add correct semantics to these elements. This helps to communicate to the Accessibility API what the component is and what it's supposed to do so that, for example, a nonsighted user knows what to expect from that component.
Android Developers' documentation has a great page on Semantics in Compose. It explains the technical aspects of semantics. More actionable information is on the same documentation's page Accessibility in Compose.
UI Tests for Semantics
You can write UI tests for Compose to verify some aspects of custom components' accessibility. Here are a couple of examples of testing custom component's name, role, and value. Let's say we have two custom components: A selectable component (e.g., radio buttons), and a toggleable component (switches). See code for these components in: Eevis Panula - Improving Android Accessibility with Modifiers in Jetpack Compose.
Let's say we have two options, "Option A" and "Option B" as selectable elements. The following code tests, that a selectable component has correct name, role, and value:
class SelectableTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun hasRoleNameValue() {
composeTestRule.setContent {
ModifiersExampleTheme {
SelectableScreen()
}
}
val selectableElements = composeTestRule.onAllNodes(
hasTestTag("accessible-selectable")
)
// Assert role
selectableElements.assertAll(isSelectable())
// Assert value
selectableElements[0].assertIsSelected()
selectableElements[1].performClick()
selectableElements[0].assertIsNotSelected()
selectableElements[1].assertIsSelected()
// Assert accessible name
selectableElements[0].assertTextContains("Option A")
selectableElements[1].assertTextContains("Option B")
}
}
This code could be written with less lines of code, but I wanted to make all the steps explicit.
The same way, if we have a toggleable element with a label "Toggleable", we can check for its the name, role, and value with the following code:
class ToggleableTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun hasRoleNameValue() {
composeTestRule.setContent {
ModifiersExampleTheme {
ToggleableScreen()
}
}
val toggleableElement = composeTestRule.onNode(
hasTestTag("accessible-toggle")
)
// Assert role
toggleableElement.assertIsToggleable()
// Assert value
toggleableElement.assertIsOff()
toggleableElement.performClick()
toggleableElement.assertIsOn()
// Assert accessible name
toggleableElement.assertTextEquals("Toggleable")
}
}
Interaction
Another aspect of custom components is interaction: Does everything work for users who are not using pointer input (touch or otherwise) in an expected way? Are there ways alternative to touch for completing actions? You will probably get an answer to these two questions by doing the other tests in the checklist.
Accessibility Actions
Accessibility actions are available only for a subset of assistive technologies - mainly TalkBack and Switch Access. That is because they both use the same APIs under the hood. This means that keyboard, magnification, and Voice Access users can't use them, so they'd need another alternative for touch gestures.
One way to add alternatives to touch gestures is to add accessibility actions. Android Developers documentation shares how to Add custom actions.
If you prefer a video format, here's a video about Jetpack Compose and accessibility by Jolanda Verhoef, embedded below. The embedded video starts from the point where she talks about adding custom accessibility actions:
UI Tests for Accessibility Actions
When writing tests for your Compose layouts, you can test for accessibility actions with performAccessibilityAction
.