When selecting a native switch with VoiceOver, the announcement will contain "Off" or "On" with an additional hint "double tap to toggle setting".
I have tried using the accessibility trait UIAccessibilityTraitSelected
, but that only results in "Selected" being announced, with no hint unless I provide one explicitly.
Using the Accessibility Inspector I've also noticed that native UIKit switches have an accessibilityValue of 1
when enabled, but providing that does not change VoiceOver behavior.
- (UIAccessibilityTraits)accessibilityTraits {
if (toggled) {
return UIAccessibilityTraitSelected;
} else {
return UIAccessibilityTraitNone;
}
}
- (NSString*)accessibilityValue {
if (toggled) {
return @"1";
} else {
return @"0"
}
}
Is it possible to provide some combination of traits/value/label such that TalkBack recognizes this element as a Switch, without using a UISwitch?
I have created an accessible view that acts like a switch here.
The only way that I have been able to get any arbitrary element to act like a Switch is when inheriting the UIAccessibilityTraits of a Switch. This causes VoiceOver to read the Accessibility Value (0
or 1
) as "Off" or "On," adds the hint "Double tap to toggle setting", and makes VoiceOver say "Switch Button."
You could potentially do this by overriding the view's Accessibility Traits like so:
override var accessibilityTraits(): UIAccessibilityTraits {
get { return UISwitch().accessibilityTraits }
set {}
}
Hope this helps!
You can create a custom accessibility element behaving like a UISwitchControl with whatever you want. The only thing to be specified is the way VoiceOver should interpret it.
Let's suppose you want to gather a label
and a view
to be seen as a switch control.
First of all, create a class for grouping these elements into a single one :
class WrapView: UIView {
static let defaultValue = "on"
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(with label: UILabel,and view: UIView) {
let viewFrame = label.frame.union(view.frame)
self.init(frame: viewFrame)
self.isAccessibilityElement = true
self.accessibilityLabel = label.accessibilityLabel
self.accessibilityValue = WrapView.defaultValue
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
}
}
Then, just create your custom view in your viewDidAppear()
:
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
@IBOutlet weak var myLabel: UILabel!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let myCustomView = WrapView.init(with: myLabel, and: myView)
self.view.addSubview(myCustomView)
}
}
Finally, to have a custom view behaving like a switch control, just override the accessibilityActivate
function in your WrapView
class to implement your logic when your view is double tapped :
override func accessibilityActivate() -> Bool {
self.accessibilityValue = (self.accessibilityValue == WrapView.defaultValue) ? "off" : "on"
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
return true
}
And now you have a custom element that contains whatever you want and that behaves like a switch control for blind people using VoiceOver without using a UISwitch as you wanted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With