Switch Name
Any Switch element should have an accessible name available for assistive technologies such as TalkBack and Voice Access.
Impact
A switch should have a name that provides the context and expectation of what happens when it is turned on or off, especially for people with low-vision or blindness.
Issues may arise depending on the focus order of the switch and its name.
Confirmation
- Turn on TalkBack
- Attempt to focus on a
Switch
control - One of the following will occur:
- Inaccessible: TalkBack only announces 'on' or 'off'.
- Accessible: TalkBack announces the name of the switch and 'on' or 'off'.
How to Fix
XML
You may provide a label in the neighboring element or wrap the switch with its label. You may also manipulate the contentDescription
, but be sure to retain the 'on' and 'off' state for TalkBack announcements.
layouts/activity.xml
<TextView
android:id="@+id/label"
android:text="@string/label_text"
android:labelFor="@+id/switch">
<Switch
android:id="@+id/switch"/>
...
strings.values/
<string name="label_text">Dark Mode</string>
Compose
In the example below, put the Text and Switch together into a merged Compose layout like a Row. Add a switch role and toggleable modifier to the Text, then clear the semantics on the Switch by using Modifier.clearAndSetSemantics { }
and it will make Talkback focus on the label but not the switch.
val (isSwitchChecked, setSwitchState) = remember {
mutableStateOf(true)
}
Row(modifier = Modifier.semantics(mergeDescendants = true) { }) {
Text(
text = "Get Emails",
modifier = Modifier
.toggleable(
value = isSwitchChecked,
onValueChange = {
setSwitchState(!isSwitchChecked)
},
role = Role.Switch
)
)
Switch(
checked = isSwitchChecked,
onCheckedChange = {
setSwitchState(!isSwitchChecked)
},
modifier = Modifier
.clearAndSetSemantics { }
)
}
React Native
To combine a switch and label in React Native, you can wrap both components within a TouchableOpacity
component:
<TouchableOpacity
onPress={() => {
setSwitchOn(!switchOn)
Alert.alert("Switch on : " + !switchOn)}}
style={styles.subContainer}
accessible={true}
accessibilityLabel={"Subscribe"}
accessibilityRole='switch'>
<Text style={{ fontSize: 22 }}>
Subscribe
</Text>
<Switch
importantForAccessibility='no-hide-descendants'
onValueChange={() => {
setSwitchOn(!switchOn)
Alert.alert("Switch on : " + !switchOn)} }
value={switchOn}
/>
</TouchableOpacity>
To ensure this functions well and provides all necessary context for both assistive technology and non-assistive technology users:
-
Ensure the
TouchableOpacity
view has theaccessible
property set to true, so that the group is focused together for assistive technology users. -
Ensure the
accessibilityLabel
property of theTouchableOpacity
component is set to the exact same value of the text label. -
Set the
TouchableOpacity
component'saccessibilityRole
toswitch
to provide the correct context to assistive technology users. -
Set the
Switch
component'simportantForAccessibility
property tono-hide-descendants
so that the component cannot be individually focused. -
Add an action via
onPress
to theTouchableOpacity
component for handling the behavior of the switch when activated.