Inaccessible Action
An element that is an active control or contains an active control must have an action that can be activated using Assistive Technology.
Impact
Assistive Technology users should be able to activate an active control's action using assistive technology.
Confirmation
- Turn on VoiceOver
- Focus on the element
- One of the following will happen:
- Inaccessible: The user will not be able to activate the active control's action using assistive technology.
- Accessible: The user will be able to use an assistive technology to activate the active control.
How to Fix
An issue is found by this rule when:
- a control and its label are within a parent view marked as isAccessibilityElement = true
- the parent view does not have a separate gesture recognizer
and/or:
- the control is not in the middle of the parent view, therefore cannot be activated with VoiceOver
UIKit
In storyboard:
- Select the element with an
InaccessibleAction
issue - Ensure that the Inspectors Panel is visible
- Select the Identity Inspector
- Under Accessibility, there is a property called "Accessibility" with a checkbox called "Enabled" next to it. Ensure that the "Enabled" check box is selected for the active control
An alternative option is to change the element's accessibility path:
- Repeat steps 1-3 for the active control, its label and the view that contains the active control
- Under Accessibility, there is a property called "Accessibility" with a checkbox called "Enabled" next to it. Ensure that the "Enabled" check box is selected for the active control, but not for the label or its containing view
- In the code, change the accessibility path to include the containing view's active control and label as shown in the second step of the fourth item in the 'In code' section
Another solution is to have the active control use it's parent's accessibility activation point:
- Select the element with an
InaccessibleAction
issue - Ensure that the Inspectors Panel is visible
- Select the active control in the element
- Select the Size Inspector
- Ensure that the active control is centered horizontally and vertically within its containing view
In code:
Find where the active control's isAccessibilityElement property was set and ensure that it is set to true.
buttonContainerView.isAccessibilityElement = true
Another option is to add a gesture recognizer to the active control's containing view. Find the view that contains the control and add a tap gesture recognizer.
buttonContainerView.addGestureRecognizer(UITapGestureRecognizer(target: self, selector: #selector(buttonTapped)))
Alternatively, you can change the active control to be in the center of the parent view, so the containing view's accessibilityActivationPoint activates the active control. Find the view that contains the control and ensure that the control is in the exact center of the parent view that contains it.
buttonContainerView.button.centerXAnchor.constraint(equalTo: buttonContainerView.centerXAnchor).isActive = true
buttonContainerView.button.centerYAnchor.constraint(equalTo: buttonContainerView.centerYAnchor).isActive = true
Additionally, you can fix this issue by changing the accessibility path to include the containing view's active control and label.
- Make the control's label and the parent view isAccessibilityElement = false
toggleContainerView.toggle.isAccessibilityElement = true
toggleContainerView.label.isAccessibilityElement = false
toggleContainerView.isAccessibilityElement = false
- Update the control's accessibility path to encapsulate both the label and the control
// Assuming we are in a ViewController
let button = UIButton()
// If not within a ViewController, self.view should be replaced with the rootView of the screen
let rootview = self.view
let onScreenFrame = button.superview!.convert(button.frame, to: rootview)
button.accessibilityPath = UIBezierPath(rect: onScreenFrame)
SwiftUI
This accessibility issue cannot occur on most default elements and active controls in SwiftUI; however, it can occur with some custom active controls such as a custom slider, stepper or toggle. Consider using the .accessibilityRepresentation view modifier to make custom controls have the same accessibility representation as the corresponding default version of the control.
// Assuming we are in a completely custom Toggle view that is not made using SwiftUI's default Toggle element
.accessibilityRepresentation {
Toggle(isOn: $isOn) {
Text("Puppy Mode")
}
}