Reputation: 13887
Our App has a few UITextField
where users enter alphanumeric input codes such as "AA149873A".
We'd like voice over to read these as "A A 1 4 9 8 7 2 A", but it instead reads the digits as a number: "One hundred and forty nine thousand, eight hundred and seventy three".
Is there some way to configure UITextField
so that it knows its content shouldn't be thought of as numbers, but individual digits?
Thanks.
Upvotes: 3
Views: 3551
Reputation: 13887
As of iOS 13 it is possible to add a string attribute to direct voice-over vocalisation to spell strings out as individual letters and digits.
I've not found a way to direct UITextField
to add this attribute to its content. However, a UITextField
subclass can override it's accessibilityValue
to achieve this.
The subclass given here adds a property to enable or disable this behaviour.
final class AccessibilityTextField: UITextField {
var isAlphanumeric: Bool = false
override public var accessibilityAttributedValue: NSAttributedString? {
get {
guard let text = text, !text.isEmpty else {
return nil
}
return NSAttributedString(string: text, attributes: valueAttributes)
}
set {
// Ignore these values.
_ = newValue
}
}
private var valueAttributes: [NSAttributedString.Key: Any] {
guard #available(iOS 13.0, *), isAlphanumeric else {
return [:]
}
return [.accessibilitySpeechSpellOut: true]
}
}
An alternative approach is given in another answer here that doesn't use the iOS 13 feature . accessibilitySpeechSpellOut
. However, I've seen it suggested that this is not ideal for brail output systems as they also use accessibilityLabel
. Perhaps this is a good fallback on pre iOS 13 systems.
Upvotes: 4
Reputation: 5671
We'd like voice over to read these as "A A 1 4 9 8 7 2 A", but it instead reads the digits as a number: "One hundred and forty nine thousand, eight hundred and seventy three".
The fastest wy to reach your goal is to add spaces between each character in the accessibilityValue
of the UITextField
as follows: 🤓
class AccessibilityTextField: UITextField {
var _str: String?
override var text: String? {
get { return _str}
set {
_str = newValue!
accessibilityValue = _str!.map{String($0)}.joined(separator: " ")
}
}
convenience init() { self.init() }
required init?(coder: NSCoder) { super.init(coder: coder) }
}
I didn't implement all the text field delegate stuff to test it ⟹ I created a blank project only with an UITextField
adding a "BB0024FG" plain text and changed the text in the viewDidAppear
of my view controller:
myTextField.text = "AA14987A"
In the end, VoiceOver spells out each character after another without reading out the initial plain text. 👍
Following this rationale, you have a way that let VoiceOver know that the UITextField
content must be thought as individual digits. 😉
Upvotes: 4