Skip to content

Commit

Permalink
Merge pull request #170 from cashapp/entin/switch-state-by-value
Browse files Browse the repository at this point in the history
  • Loading branch information
NickEntin authored Nov 17, 2023
2 parents 0f195fb + 9a0db5a commit 9a72e64
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 65 deletions.
65 changes: 32 additions & 33 deletions Example/AccessibilitySnapshot/SwitchControlViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,36 @@ private extension SwitchControlViewController {

switchControls.forEach { addSubview($0) }

let switchTrait = UIAccessibilityTraits(rawValue: 0x0020000000000000)

// Add a fake switch that has the switch button trait only, but is not a UISwitch.
fakeSwitchView.isAccessibilityElement = true
fakeSwitchView.accessibilityLabel = "Fake Label"
fakeSwitchView.accessibilityValue = "Value"
fakeSwitchView.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000))
fakeSwitchView.frame.size = .init(width: 48, height: 32)
fakeSwitchView.backgroundColor = .lightGray
fakeSwitchView.layer.cornerRadius = 16
addSubview(fakeSwitchView)

// Add a fake switch that has the switch button and button traits, but is not a UISwitch.
fakeSwitchButton.isAccessibilityElement = true
fakeSwitchButton.accessibilityLabel = "Fake Label"
fakeSwitchButton.accessibilityValue = "Value"
fakeSwitchButton.accessibilityTraits.insert(.button)
fakeSwitchButton.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000))
fakeSwitchButton.frame.size = .init(width: 48, height: 32)
fakeSwitchButton.backgroundColor = .lightGray
fakeSwitchButton.layer.cornerRadius = 16
addSubview(fakeSwitchButton)
for fakeSwitchView in fakeSwitchViews {
fakeSwitchView.isAccessibilityElement = true
fakeSwitchView.accessibilityLabel = "Fake Label"
fakeSwitchView.frame.size = .init(width: 48, height: 32)
fakeSwitchView.backgroundColor = .lightGray
fakeSwitchView.layer.cornerRadius = 16
}

fakeSwitchViews[0].accessibilityValue = "1"
fakeSwitchViews[0].accessibilityTraits = [switchTrait, .button]

fakeSwitchViews[1].accessibilityValue = "0"
fakeSwitchViews[1].accessibilityTraits = [switchTrait, .button]

fakeSwitchViews[2].accessibilityValue = "2"
fakeSwitchViews[2].accessibilityTraits = [switchTrait, .button]

fakeSwitchViews[3].accessibilityValue = "1"
fakeSwitchViews[3].accessibilityTraits = [switchTrait]

fakeSwitchViews[4].accessibilityValue = "3"
fakeSwitchViews[4].accessibilityTraits = [switchTrait]

fakeSwitchViews[5].accessibilityValue = "Value"
fakeSwitchViews[5].accessibilityTraits = [.button, switchTrait]

fakeSwitchViews.forEach { addSubview($0) }
}

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

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

/// UIView with the switch button trait that acts like a switch, but is not a UISwitch.
private let fakeSwitchView: UIView = .init()

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

// MARK: - UIView

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

var distributionSpecifiers: [ViewDistributionSpecifying] = [ statusBarHeight.fixed, 1.flexible ]
for subview in switchControls {
for subview in (switchControls + fakeSwitchViews) {
distributionSpecifiers.append(subview)
distributionSpecifiers.append(1.flexible)
}
distributionSpecifiers.append(
contentsOf: [
fakeSwitchView.distributionItem,
1.flexible,
fakeSwitchButton.distributionItem,
1.flexible,
]
)
applyVerticalSubviewDistribution(distributionSpecifiers)
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@
"trait.search_field.description" = "Suchfeld.";

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

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

/* Description for the 'switch button' accessibility trait, when the state of the switch cannot be determined */
"trait.switch_button.state_unspecified.description" = "Umschalttaste.";
/* Description for the 'switch button' accessibility trait, when the switch is in a mixed state */
"trait.switch_button.state_mixed.description" = "Gemischt.";

/* Description for the 'switch button' accessibility trait */
"trait.switch_button.description" = "Umschalttaste.";

/* Hint describing how to use elements with the 'switch button' accessibility trait */
"trait.switch_button.hint" = "Zum Umschalten Doppeltippen.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@
"trait.search_field.description" = "Search Field.";

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

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

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

/* Description for the 'switch button' accessibility trait */
"trait.switch_button.description" = "Switch Button.";

/* Hint describing how to use elements with the 'switch button' accessibility trait */
"trait.switch_button.hint" = "Double tap to toggle setting.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@
"trait.search_field.description" = "Поле поиска.";

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

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

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

/* Description for the 'switch button' accessibility trait */
"trait.switch_button.description" = "Кнопка-переключатель.";

/* Hint describing how to use elements with the 'switch button' accessibility trait */
"trait.switch_button.hint" = "Коснитесь дважды, чтобы переключить настройку.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,23 @@ extension NSObject {
}

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

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

Expand Down Expand Up @@ -304,11 +308,13 @@ extension NSObject {

let searchFieldTraitName: String

let switchButtonOnTraitName: String
let switchButtonTraitName: String

let switchButtonOffTraitName: String
let switchButtonOnStateName: String

let switchButtonStatelessTraitName: String
let switchButtonOffStateName: String

let switchButtonMixedStateName: String

let switchButtonTraitHint: String

Expand Down Expand Up @@ -396,19 +402,24 @@ extension NSObject {
comment: "Description for the 'search field' accessibility trait",
locale: locale
)
self.switchButtonOnTraitName = "Switch Button. On.".localized(
self.switchButtonTraitName = "Switch Button.".localized(
key: "trait.switch_button.description",
comment: "Description for the 'switch button' accessibility trait",
locale: locale
)
self.switchButtonOnStateName = "On.".localized(
key: "trait.switch_button.state_on.description",
comment: "Description for the 'switch button' accessibility trait, when the switch is on",
locale: locale
)
self.switchButtonOffTraitName = "Switch Button. Off.".localized(
self.switchButtonOffStateName = "Off.".localized(
key: "trait.switch_button.state_off.description",
comment: "Description for the 'switch button' accessibility trait, when the switch is off",
locale: locale
)
self.switchButtonStatelessTraitName = "Switch Button.".localized(
key: "trait.switch_button.state_unspecified.description",
comment: "Description for the 'switch button' accessibility trait, when the state of the switch cannot be determined",
self.switchButtonMixedStateName = "Mixed.".localized(
key: "trait.switch_button.state_mixed.description",
comment: "Description for the 'switch button' accessibility trait, when the switch is in a mixed state",
locale: locale
)
self.switchButtonTraitHint = "Double tap to toggle setting.".localized(
Expand Down

0 comments on commit 9a72e64

Please sign in to comment.