Video examples
iOS Voiceover
Android Talkback
iOS
Developer notes
- A stepper is a two-segment control used to increase or decrease an incremental value
- When new value changes, it gets announced dynamically without moving focus from the increment/decrement button
- Announcing the label when appropriate with the value gives the screen reader users and users with memory challenges context
Name
- If visible text label exists, the programmatic name should match the visible text label.
- Note: Setting a programmatic name while a visible text label exists may cause VoiceOver to duplicate the announcement of the name. If this happens, hide the visible text label from VoiceOver recognization.
- UIKit
- You can programmatically set the visible label with
setTitle()
.- The stepper’s title will overwrite the segment’s
accessibilityLabel
.
- The stepper’s title will overwrite the segment’s
- To hide labels from VoiceOver programmatically, set the label’s
isAccessibilityElement
property tofalse
- To hide labels from VoiceOver using Interface Builder, uncheck
Accessibility Enabled
in the Identity Inspector.
- You can programmatically set the visible label with
- SwiftUI
- By default, the programmatic name is the visible text label of the segment
- If necessary, use view modifier
accessibilityLabel(_:)
. - If a segment has icon(s), hide the icon(s) from VoiceOver by using view modifier
accessibilityHidden(true)
.
Role
- The presence of the stepper buttons implies an interactive stepper component.
-
The stepper buttons themselves should be announced as “Button”.
- UIKit
- Use
UIStepper
- Use
- SwiftUI
- Use native
Stepper
view
- Use native
Groupings
-
N/A
- UIKit
- Follow native grouping and order
- SwiftUI
- Follow native grouping and order
State
- The stepper button’s state should be announced as “Increment” or “Decrement”.
-
The new value should be announced when the user activates one of the buttons.
- UIKit
- For disabled stepper: Set
isEnabled
tofalse
. Announcement for disabled is “Dimmed”.- If necessary, you may change the accessibility trait of the menu item to
notEnabled
, but this may overwrite the current accessibility role of the segmented control.
- If necessary, you may change the accessibility trait of the menu item to
- For disabled stepper: Set
- SwiftUI
- For disabled, use view modifier
disabled()
.
- For disabled, use view modifier
Focus
- Use the device’s default focus functionality.
-
External keyboard tab order often follows the screen reader focus, but sometimes this functionality requires additional development to manage focus.
- UIKit
- If VoiceOver is not reaching a particular element, set the element’s
isAccessibilityElement
totrue
- Note: You may need to adjust the programmatic name, role, state, and/or value after doing this, as this action may overwrite previously configured accessibility.
- To move screen reader focus to newly revealed content, use
UIAccessibility.post(notification:argument:)
that takes in.screenChanged
and the newly revealed content as the parameter arguments. - To NOT move focus, but dynamically announce new content: use
UIAccessibility.post(notification:argument:)
that takes in.announcement
and the announcement text as the parameter arguments. UIAccessibilityContainer
protocol: Have a table of elements that defines the reading order of the elements.
- If VoiceOver is not reaching a particular element, set the element’s
- SwiftUI
- For general focus management that impacts both screen readers and non-screen readers, use the property wrapper
@FocusState
to assign an identity of a focus state.- Use the property wrapper
@FocusState
in conjunction with the view modifierfocused(_:)
to assign focus on a view with@FocusState
as the source of truth. - Use the property wrapper
@FocusState
in conjunction with the view modifierfocused(_:equals:)
to assign focus on a view, when the view is equal to a specific value.
- Use the property wrapper
- If necessary, use property wrapper
@AccessibilityFocusState
to assign identifiers to specific views to manually shift focus from one view to another as the user interacts with the screen with VoiceOver on.
- For general focus management that impacts both screen readers and non-screen readers, use the property wrapper
Announcements
- Increment
- “Label with current value, Increment, Button”
- if button is activated new value will dynamically announce
- Decrement
- “Label with current value, Decrement, Button”
- if button is activated new value will dynamically announce
Android
There is no native stepper element for Android. The notes below are suggestions and accessibility guidance.
Developer notes
- A stepper is a two-segment control used to increase or decrease an incremental value
- When new value changes, it gets announced dynamically without moving focus from the increment/decrement button
- Announcing the label when appropriate with the value gives the screen reader users and users with memory challenges context
Name
-
Name includes the purpose and describes the item changing, matching any visible label and references the number shown between stepper (if visible).
- android:text XML attribute
- Optional: use contentDescription for a more descriptive name, depending on type of view and for elements without a visible label.
- contentDescription overrides android:text
- Use labelFor attribute to connect the visible label to the control
Role
- Extend the most relevant View subclass as is relevant to this control
- Button or ImageButton
State
- Active: android:enabled=true
- Disabled: android:enabled=false
- Announcement: disabled
Focus
- 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.
- android:focusable=true
- android=clickable=true
- Implement an onClick( ) event handler for keyboard, not onTouch( )
- nextFocusDown
- nextFocusUp
- nextFocusRight
- nextFocusLeft
- accessibilityTraversalBefore (or after)
- To move screen reader focus to newly revealed content: Type_View_Focused
- To NOT move focus, but announce new content: accessibilityLiveRegion
- To hide controls: Important_For _Accessibility_NO
Announcements
- Increment
- “Label with value, Increment, Double tap to activate”
- if button is activated new value will dynamically announce
- Decrement
- “Label with value, Decrement, Double tap to activate”
- if button is activated new value will dynamically announce