Skip to content

Commit e0ec1c6

Browse files
Add support for back button accessibility trait. (#219)
* adding back button trait
1 parent 4ea8cbf commit e0ec1c6

File tree

14 files changed

+175
-9
lines changed

14 files changed

+175
-9
lines changed

Example/AccessibilitySnapshot.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
66E2CD14CD63946657E17B15 /* Pods_SnapshotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3192D7B9B16BD10FB517A2 /* Pods_SnapshotTests.framework */; };
5858
83A295842AC22D9D00DFBE4F /* UserInputLabelsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83A295832AC22D9D00DFBE4F /* UserInputLabelsViewController.swift */; };
5959
83A295862AC22EEE00DFBE4F /* UserInputLabelsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83A295852AC22EEE00DFBE4F /* UserInputLabelsTests.swift */; };
60+
AC5C5FE22C627DA300E1C4E7 /* NavBarBackButtonAccessibilityTraitsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC5C5FE12C627DA300E1C4E7 /* NavBarBackButtonAccessibilityTraitsViewController.swift */; };
6061
AC725B842B06D07E009AD59B /* AccessibilityCustomContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC725B832B06D07E009AD59B /* AccessibilityCustomContentViewController.swift */; };
6162
C47F6C5316FB0C043BEB59F3 /* Pods_AccessibilitySnapshotDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A886964D2E787399E137105 /* Pods_AccessibilitySnapshotDemo.framework */; };
6263
D2F76EED2945C879000A453F /* HitTargetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2F76EEC2945C879000A453F /* HitTargetTests.swift */; };
@@ -149,6 +150,7 @@
149150
83A295832AC22D9D00DFBE4F /* UserInputLabelsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInputLabelsViewController.swift; sourceTree = "<group>"; };
150151
83A295852AC22EEE00DFBE4F /* UserInputLabelsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInputLabelsTests.swift; sourceTree = "<group>"; };
151152
88C33CBF672C290CE1EE86AF /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
153+
AC5C5FE12C627DA300E1C4E7 /* NavBarBackButtonAccessibilityTraitsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavBarBackButtonAccessibilityTraitsViewController.swift; sourceTree = "<group>"; };
152154
AC725B832B06D07E009AD59B /* AccessibilityCustomContentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityCustomContentViewController.swift; sourceTree = "<group>"; };
153155
C78F90CE7A2A315AADF80144 /* Pods-SnapshotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SnapshotTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SnapshotTests/Pods-SnapshotTests.debug.xcconfig"; sourceTree = "<group>"; };
154156
CCFF2A604706B71DC0CBD38B /* Pods-AccessibilitySnapshotDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AccessibilitySnapshotDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-AccessibilitySnapshotDemo/Pods-AccessibilitySnapshotDemo.release.xcconfig"; sourceTree = "<group>"; };
@@ -195,6 +197,7 @@
195197
3F8E5DB82535B25000276B32 /* SwiftUIView.swift */,
196198
3FEF854E253846420072611F /* SwiftUIViewWithScrollView.swift */,
197199
3D39BFAB223314C1009C3EF4 /* TabBarViewController.swift */,
200+
AC5C5FE12C627DA300E1C4E7 /* NavBarBackButtonAccessibilityTraitsViewController.swift */,
198201
3D04B6D821155942006218A4 /* LabelAccessibilityPropertiesViewController.swift */,
199202
3D04B6DA21155D92006218A4 /* ButtonAccessibilityTraitsViewController.swift */,
200203
3D9894F8213509C8006C16F6 /* DescriptionEdgeCasesViewController.swift */,
@@ -647,6 +650,7 @@
647650
3DDE7FF624C6D6BF00999ABA /* AccessibilityCustomActionsViewController.swift in Sources */,
648651
3DBAC28F2242E7C700EF4D0A /* ListContainerViewController.swift in Sources */,
649652
AC725B842B06D07E009AD59B /* AccessibilityCustomContentViewController.swift in Sources */,
653+
AC5C5FE22C627DA300E1C4E7 /* NavBarBackButtonAccessibilityTraitsViewController.swift in Sources */,
650654
3DBEAA5B2222953E00FAE61D /* SwitchControlViewController.swift in Sources */,
651655
3DBAC2912242F9B200EF4D0A /* LandmarkContainerViewController.swift in Sources */,
652656
1104A8CF2B580AC500B6715F /* SwiftUITextEntry.swift in Sources */,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//
2+
// Copyright 2024 Square Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
import Paralayout
18+
import UIKit
19+
20+
final class NavBarBackButtonAccessibilityTraitsViewController: AccessibilityViewController {
21+
22+
// MARK: - Public Properties
23+
24+
init(titles: [String?] = [nil, nil]) {
25+
self.titles = titles
26+
super.init(nibName: nil, bundle: nil)
27+
}
28+
29+
required init?(coder: NSCoder) {
30+
fatalError("init(coder:) has not been implemented")
31+
}
32+
33+
var titles: [String?]
34+
35+
// MARK: - Private Properties
36+
37+
private var rootView: View {
38+
return view as! View
39+
}
40+
41+
// MARK: - UIViewController
42+
43+
override func loadView() {
44+
view = View(titles: titles)
45+
}
46+
}
47+
48+
// MARK: -
49+
50+
extension NavBarBackButtonAccessibilityTraitsViewController {
51+
52+
final class Child: UIViewController {
53+
54+
init(_ title: String? = nil) {
55+
super.init(nibName: nil, bundle: nil)
56+
self.title = title
57+
}
58+
59+
required init?(coder: NSCoder) {
60+
super.init(coder: coder)
61+
}
62+
let label = UILabel()
63+
64+
override func viewDidLoad() {
65+
super.viewDidLoad()
66+
navigationItem.hidesBackButton = false
67+
68+
label.text = "Back Button Accessibility Traits - "
69+
label.text?.append(hasTitle ? "With Titles" : "Without Titles" )
70+
view.addSubview(label)
71+
}
72+
private var hasTitle: Bool {
73+
self.title != nil
74+
}
75+
76+
override func viewDidLayoutSubviews() {
77+
super.viewDidLayoutSubviews()
78+
label.sizeToFit()
79+
let x = (view.bounds.width / 2) - (label.frame.size.width / 2)
80+
let y = (view.bounds.height / 2) - (label.frame.size.height / 2)
81+
label.frame = CGRect(origin: CGPoint(x: x, y: y), size: label.frame.size)
82+
}
83+
}
84+
}
85+
86+
extension NavBarBackButtonAccessibilityTraitsViewController {
87+
88+
final class View: UIView {
89+
90+
// MARK: - Life Cycle
91+
92+
init(titles: [String?]) {
93+
self.titles = titles
94+
super.init(frame: .zero)
95+
addSubview(navView)
96+
navController.viewControllers = titles.map { Child($0) }
97+
}
98+
99+
@available(*, unavailable)
100+
required init?(coder: NSCoder) {
101+
fatalError("init(coder:) has not been implemented")
102+
}
103+
104+
// MARK: - Public Properties
105+
var titles: [String?]
106+
107+
let navController = UINavigationController()
108+
var navView: UIView {
109+
navController.view
110+
}
111+
112+
113+
114+
// MARK: - Private Properties
115+
116+
// MARK: - UIView
117+
118+
override func layoutSubviews() {
119+
super.layoutSubviews()
120+
navView.frame = bounds
121+
}
122+
123+
124+
}
125+
126+
}

Example/AccessibilitySnapshot/RootViewController.swift

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ final class RootViewController: UITableViewController {
2929
var accessibilityScreens = [
3030
("View Accessibility Properties", { _ in return ViewAccessibilityPropertiesViewController() }),
3131
("Label Accessibility Properties", { _ in return LabelAccessibilityPropertiesViewController() }),
32+
("Nav Bar Back Button Accessibility Traits", { _ in return NavBarBackButtonAccessibilityTraitsViewController() }),
3233
("Button Accessibility Traits", { _ in return ButtonAccessibilityTraitsViewController() }),
3334
("Default UIKit Controls", { _ in return DefaultControlsViewController() }),
3435
("UISwitch Controls", { _ in return SwitchControlViewController() }),

Example/SnapshotTests/AccessibilityPropertiesTests.swift

+12
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ final class AccessibilitySnapshotTests: SnapshotTestCase {
3939
buttonTraitsViewController.view.frame = UIScreen.main.bounds
4040
SnapshotVerifyAccessibility(buttonTraitsViewController.view)
4141
}
42+
43+
func testNavBarBackButtonTraitsWithTitles() {
44+
let navBarBackButtonTraitsViewController = NavBarBackButtonAccessibilityTraitsViewController(titles: ["First", "Second"])
45+
navBarBackButtonTraitsViewController.view.frame = UIScreen.main.bounds
46+
SnapshotVerifyAccessibility(navBarBackButtonTraitsViewController.view)
47+
}
48+
func testNavBarBackButtonTraitsWithoutTitles() {
49+
let navBarBackButtonTraitsViewController = NavBarBackButtonAccessibilityTraitsViewController()
50+
navBarBackButtonTraitsViewController.view.frame = UIScreen.main.bounds
51+
52+
SnapshotVerifyAccessibility(navBarBackButtonTraitsViewController.view)
53+
}
4254

4355
func testSwitchControls() {
4456
let switchControlViewController = SwitchControlViewController()

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

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
/* Description for the 'button' accessibility trait */
1111
"trait.button.description" = "Taste.";
1212

13+
/* Description for the 'back button' accessibility trait */
14+
"trait.backbutton.description" = "Zurück Taste.";
15+
1316
/* Description for the 'tab' accessibility trait */
1417
"trait.tab.description" = "Tabulator.";
1518

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

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
/* Description for the 'button' accessibility trait */
1111
"trait.button.description" = "Button.";
1212

13+
/* Description for the 'back button' accessibility trait */
14+
"trait.backbutton.description" = "Back Button.";
15+
1316
/* Description for the 'tab' accessibility trait */
1417
"trait.tab.description" = "Tab.";
1518

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

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
/* Description for the 'button' accessibility trait */
1111
"trait.button.description" = "Кнопка.";
1212

13+
/* Description for the 'back button' accessibility trait */
14+
"trait.backbutton.description" = "Кнопка назад.";
15+
1316
/* Description for the 'tab' accessibility trait */
1417
"trait.tab.description" = "Вкладка.";
1518

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

+23-9
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,14 @@ extension NSObject {
101101
}
102102

103103
let hidesButtonTraitInContext = context?.hidesButtonTrait ?? false
104-
let hidesButtonTraitFromTraits = [UIAccessibilityTraits.keyboardKey, .switchButton, .tabBarItem].contains(where: { accessibilityTraits.contains($0) })
104+
let hidesButtonTraitFromTraits = [UIAccessibilityTraits.keyboardKey, .switchButton, .tabBarItem, .backButton].contains(where: { accessibilityTraits.contains($0) })
105105
if accessibilityTraits.contains(.button) && !hidesButtonTraitFromTraits && !hidesButtonTraitInContext {
106106
traitSpecifiers.append(strings.buttonTraitName)
107107
}
108+
109+
if accessibilityTraits.contains(.backButton) {
110+
traitSpecifiers.append(strings.backButtonTraitName)
111+
}
108112

109113
if accessibilityTraits.contains(.switchButton) {
110114
if accessibilityTraits.contains(.button) {
@@ -319,6 +323,8 @@ extension NSObject {
319323
let notEnabledTraitName: String
320324

321325
let buttonTraitName: String
326+
327+
let backButtonTraitName: String
322328

323329
let tabTraitName: String
324330

@@ -399,6 +405,11 @@ extension NSObject {
399405
comment: "Description for the 'button' accessibility trait",
400406
locale: locale
401407
)
408+
self.backButtonTraitName = "Back Button.".localized(
409+
key: "trait.backbutton.description",
410+
comment: "Description for the 'back button' accessibility trait",
411+
locale: locale
412+
)
402413
self.tabTraitName = "Tab.".localized(
403414
key: "trait.tab.description",
404415
comment: "Description for the 'tab' accessibility trait",
@@ -571,15 +582,18 @@ extension String {
571582

572583
extension UIAccessibilityTraits {
573584

574-
static let tabBarItem = UIAccessibilityTraits(rawValue: 0x0000000010000000)
575-
576-
static let switchButton = UIAccessibilityTraits(rawValue: 0x0020000000000000)
577-
578-
static let isEditing = UIAccessibilityTraits(rawValue: 0x0000000000200000)
579-
580-
static let textEntry = UIAccessibilityTraits(rawValue: 0x0000000000040000)
585+
static let textEntry = UIAccessibilityTraits(rawValue: 1 << 18) // 0x0000000000040000
586+
587+
static let isEditing = UIAccessibilityTraits(rawValue: 1 << 21) // 0x0000000000200000
588+
589+
static let backButton = UIAccessibilityTraits(rawValue: 1 << 27) // 0x0000000008000000
590+
591+
static let tabBarItem = UIAccessibilityTraits(rawValue: 1 << 28) // 0x0000000010000000
592+
593+
static let scrollable = UIAccessibilityTraits(rawValue: 1 << 47) // 0x0000800000000000
594+
595+
static let switchButton = UIAccessibilityTraits(rawValue: 1 << 53) //0x0020000000000000
581596

582-
static let scrollable = UIAccessibilityTraits(rawValue: 0x0000800000000000)
583597
}
584598

585599
// MARK: -

0 commit comments

Comments
 (0)