Skip to content

Commit 9a0db5a

Browse files
committed
Check UISwitch state using combination of trait and value
1 parent 0f195fb commit 9a0db5a

File tree

8 files changed

+84
-65
lines changed

8 files changed

+84
-65
lines changed

Example/AccessibilitySnapshot/SwitchControlViewController.swift

+32-33
Original file line numberDiff line numberDiff line change
@@ -91,26 +91,36 @@ private extension SwitchControlViewController {
9191

9292
switchControls.forEach { addSubview($0) }
9393

94+
let switchTrait = UIAccessibilityTraits(rawValue: 0x0020000000000000)
95+
9496
// Add a fake switch that has the switch button trait only, but is not a UISwitch.
95-
fakeSwitchView.isAccessibilityElement = true
96-
fakeSwitchView.accessibilityLabel = "Fake Label"
97-
fakeSwitchView.accessibilityValue = "Value"
98-
fakeSwitchView.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000))
99-
fakeSwitchView.frame.size = .init(width: 48, height: 32)
100-
fakeSwitchView.backgroundColor = .lightGray
101-
fakeSwitchView.layer.cornerRadius = 16
102-
addSubview(fakeSwitchView)
103-
104-
// Add a fake switch that has the switch button and button traits, but is not a UISwitch.
105-
fakeSwitchButton.isAccessibilityElement = true
106-
fakeSwitchButton.accessibilityLabel = "Fake Label"
107-
fakeSwitchButton.accessibilityValue = "Value"
108-
fakeSwitchButton.accessibilityTraits.insert(.button)
109-
fakeSwitchButton.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000))
110-
fakeSwitchButton.frame.size = .init(width: 48, height: 32)
111-
fakeSwitchButton.backgroundColor = .lightGray
112-
fakeSwitchButton.layer.cornerRadius = 16
113-
addSubview(fakeSwitchButton)
97+
for fakeSwitchView in fakeSwitchViews {
98+
fakeSwitchView.isAccessibilityElement = true
99+
fakeSwitchView.accessibilityLabel = "Fake Label"
100+
fakeSwitchView.frame.size = .init(width: 48, height: 32)
101+
fakeSwitchView.backgroundColor = .lightGray
102+
fakeSwitchView.layer.cornerRadius = 16
103+
}
104+
105+
fakeSwitchViews[0].accessibilityValue = "1"
106+
fakeSwitchViews[0].accessibilityTraits = [switchTrait, .button]
107+
108+
fakeSwitchViews[1].accessibilityValue = "0"
109+
fakeSwitchViews[1].accessibilityTraits = [switchTrait, .button]
110+
111+
fakeSwitchViews[2].accessibilityValue = "2"
112+
fakeSwitchViews[2].accessibilityTraits = [switchTrait, .button]
113+
114+
fakeSwitchViews[3].accessibilityValue = "1"
115+
fakeSwitchViews[3].accessibilityTraits = [switchTrait]
116+
117+
fakeSwitchViews[4].accessibilityValue = "3"
118+
fakeSwitchViews[4].accessibilityTraits = [switchTrait]
119+
120+
fakeSwitchViews[5].accessibilityValue = "Value"
121+
fakeSwitchViews[5].accessibilityTraits = [.button, switchTrait]
122+
123+
fakeSwitchViews.forEach { addSubview($0) }
114124
}
115125

116126
@available(*, unavailable)
@@ -122,11 +132,8 @@ private extension SwitchControlViewController {
122132

123133
private let switchControls: [UISwitch] = (0..<9).map { _ in UISwitch() }
124134

125-
/// UIView with the switch button trait that acts like a switch, but is not a UISwitch.
126-
private let fakeSwitchView: UIView = .init()
127-
128-
/// UIView with the button and switch button traits that acts like a switch, but is not a UISwitch.
129-
private let fakeSwitchButton: UIView = .init()
135+
/// `UIView`s with the switch button trait that act like a switch, but aren't actually switches.
136+
private let fakeSwitchViews: [UIView] = (0..<6).map { _ in UIView() }
130137

131138
// MARK: - UIView
132139

@@ -136,18 +143,10 @@ private extension SwitchControlViewController {
136143
let statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
137144

138145
var distributionSpecifiers: [ViewDistributionSpecifying] = [ statusBarHeight.fixed, 1.flexible ]
139-
for subview in switchControls {
146+
for subview in (switchControls + fakeSwitchViews) {
140147
distributionSpecifiers.append(subview)
141148
distributionSpecifiers.append(1.flexible)
142149
}
143-
distributionSpecifiers.append(
144-
contentsOf: [
145-
fakeSwitchView.distributionItem,
146-
1.flexible,
147-
fakeSwitchButton.distributionItem,
148-
1.flexible,
149-
]
150-
)
151150
applyVerticalSubviewDistribution(distributionSpecifiers)
152151
}
153152

Sources/AccessibilitySnapshot/Core/Swift/Assets/de.lproj/Localizable.strings

+7-4
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@
3535
"trait.search_field.description" = "Suchfeld.";
3636

3737
/* Description for the 'switch button' accessibility trait, when the switch is on */
38-
"trait.switch_button.state_on.description" = "Umschalttaste. Ein.";
38+
"trait.switch_button.state_on.description" = "Ein.";
3939

4040
/* Description for the 'switch button' accessibility trait, when the switch is off */
41-
"trait.switch_button.state_off.description" = "Umschalttaste. Aus.";
41+
"trait.switch_button.state_off.description" = "Aus.";
4242

43-
/* Description for the 'switch button' accessibility trait, when the state of the switch cannot be determined */
44-
"trait.switch_button.state_unspecified.description" = "Umschalttaste.";
43+
/* Description for the 'switch button' accessibility trait, when the switch is in a mixed state */
44+
"trait.switch_button.state_mixed.description" = "Gemischt.";
45+
46+
/* Description for the 'switch button' accessibility trait */
47+
"trait.switch_button.description" = "Umschalttaste.";
4548

4649
/* Hint describing how to use elements with the 'switch button' accessibility trait */
4750
"trait.switch_button.hint" = "Zum Umschalten Doppeltippen.";

Sources/AccessibilitySnapshot/Core/Swift/Assets/en.lproj/Localizable.strings

+7-4
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@
3535
"trait.search_field.description" = "Search Field.";
3636

3737
/* Description for the 'switch button' accessibility trait, when the switch is on */
38-
"trait.switch_button.state_on.description" = "Switch Button. On.";
38+
"trait.switch_button.state_on.description" = "On.";
3939

4040
/* Description for the 'switch button' accessibility trait, when the switch is off */
41-
"trait.switch_button.state_off.description" = "Switch Button. Off.";
41+
"trait.switch_button.state_off.description" = "Off.";
4242

43-
/* Description for the 'switch button' accessibility trait, when the state of the switch cannot be determined */
44-
"trait.switch_button.state_unspecified.description" = "Switch Button.";
43+
/* Description for the 'switch button' accessibility trait, when the switch is in a mixed state */
44+
"trait.switch_button.state_mixed.description" = "Mixed.";
45+
46+
/* Description for the 'switch button' accessibility trait */
47+
"trait.switch_button.description" = "Switch Button.";
4548

4649
/* Hint describing how to use elements with the 'switch button' accessibility trait */
4750
"trait.switch_button.hint" = "Double tap to toggle setting.";

Sources/AccessibilitySnapshot/Core/Swift/Assets/ru.lproj/Localizable.strings

+7-4
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@
3535
"trait.search_field.description" = "Поле поиска.";
3636

3737
/* Description for the 'switch button' accessibility trait, when the switch is on */
38-
"trait.switch_button.state_on.description" = "Кнопка-переключатель. Вкл.";
38+
"trait.switch_button.state_on.description" = "Вкл.";
3939

4040
/* Description for the 'switch button' accessibility trait, when the switch is off */
41-
"trait.switch_button.state_off.description" = "Кнопка-переключатель. Выкл.";
41+
"trait.switch_button.state_off.description" = "Выкл.";
4242

43-
/* Description for the 'switch button' accessibility trait, when the state of the switch cannot be determined */
44-
"trait.switch_button.state_unspecified.description" = "Кнопка-переключатель.";
43+
/* Description for the 'switch button' accessibility trait, when the switch is in a mixed state */
44+
"trait.switch_button.state_mixed.description" = "Смешанно.";
45+
46+
/* Description for the 'switch button' accessibility trait */
47+
"trait.switch_button.description" = "Кнопка-переключатель.";
4548

4649
/* Hint describing how to use elements with the 'switch button' accessibility trait */
4750
"trait.switch_button.hint" = "Коснитесь дважды, чтобы переключить настройку.";

Sources/AccessibilitySnapshot/Core/Swift/Classes/UIAccessibility+SnapshotAdditions.swift

+31-20
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,23 @@ extension NSObject {
107107
}
108108

109109
if accessibilityTraits.contains(.switchButton) {
110-
if let `self` = self as? UISwitch {
111-
if self.isOn {
112-
traitSpecifiers.append(strings.switchButtonOnTraitName)
113-
} else {
114-
traitSpecifiers.append(strings.switchButtonOffTraitName)
115-
}
110+
if accessibilityTraits.contains(.button) {
111+
// An element can have the private switch button trait without being a UISwitch (for example, by passing
112+
// through the traits of a contained switch). In this case, VoiceOver will still read the "Switch
113+
// Button." trait, but only if the element's traits also include the `.button` trait.
114+
traitSpecifiers.append(strings.switchButtonTraitName)
115+
}
116116

117-
} else if accessibilityTraits.contains(.button) {
118-
// An element can have the private switch button trait without being a UISwitch (for example, by passing through
119-
// the traits of a contained switch). In this case, VoiceOver will still read the "Switch Button." trait, but
120-
// will not read whether or not the switch is turned on. If the element's traits do not also include the `.button`
121-
// trait, VoiceOver will not read the trait description.
122-
traitSpecifiers.append(strings.switchButtonStatelessTraitName)
117+
switch accessibilityValue {
118+
case "1":
119+
traitSpecifiers.append(strings.switchButtonOnStateName)
120+
case "0":
121+
traitSpecifiers.append(strings.switchButtonOffStateName)
122+
case "2":
123+
traitSpecifiers.append(strings.switchButtonMixedStateName)
124+
default:
125+
// When the switch button trait is set, unknown accessibility values are omitted from the description.
126+
break
123127
}
124128
}
125129

@@ -304,11 +308,13 @@ extension NSObject {
304308

305309
let searchFieldTraitName: String
306310

307-
let switchButtonOnTraitName: String
311+
let switchButtonTraitName: String
308312

309-
let switchButtonOffTraitName: String
313+
let switchButtonOnStateName: String
310314

311-
let switchButtonStatelessTraitName: String
315+
let switchButtonOffStateName: String
316+
317+
let switchButtonMixedStateName: String
312318

313319
let switchButtonTraitHint: String
314320

@@ -396,19 +402,24 @@ extension NSObject {
396402
comment: "Description for the 'search field' accessibility trait",
397403
locale: locale
398404
)
399-
self.switchButtonOnTraitName = "Switch Button. On.".localized(
405+
self.switchButtonTraitName = "Switch Button.".localized(
406+
key: "trait.switch_button.description",
407+
comment: "Description for the 'switch button' accessibility trait",
408+
locale: locale
409+
)
410+
self.switchButtonOnStateName = "On.".localized(
400411
key: "trait.switch_button.state_on.description",
401412
comment: "Description for the 'switch button' accessibility trait, when the switch is on",
402413
locale: locale
403414
)
404-
self.switchButtonOffTraitName = "Switch Button. Off.".localized(
415+
self.switchButtonOffStateName = "Off.".localized(
405416
key: "trait.switch_button.state_off.description",
406417
comment: "Description for the 'switch button' accessibility trait, when the switch is off",
407418
locale: locale
408419
)
409-
self.switchButtonStatelessTraitName = "Switch Button.".localized(
410-
key: "trait.switch_button.state_unspecified.description",
411-
comment: "Description for the 'switch button' accessibility trait, when the state of the switch cannot be determined",
420+
self.switchButtonMixedStateName = "Mixed.".localized(
421+
key: "trait.switch_button.state_mixed.description",
422+
comment: "Description for the 'switch button' accessibility trait, when the switch is in a mixed state",
412423
locale: locale
413424
)
414425
self.switchButtonTraitHint = "Double tap to toggle setting.".localized(

0 commit comments

Comments
 (0)