Skip to content

Commit 391cdd0

Browse files
author
David Brunow
committed
Make implementation match VoiceOver
1 parent c3eb5d0 commit 391cdd0

File tree

8 files changed

+110
-14
lines changed

8 files changed

+110
-14
lines changed

Example/AccessibilitySnapshot.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
1104A8CF2B580AC500B6715F /* SwiftUITextEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1104A8CE2B580AC500B6715F /* SwiftUITextEntry.swift */; };
11+
1104A8D12B595FF600B6715F /* TextInputsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1104A8D02B595FF600B6715F /* TextInputsViewController.swift */; };
1112
1635CE4E251EAC6700907101 /* SnapshotTestingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1635CE4D251EAC6700907101 /* SnapshotTestingTests.swift */; };
1213
3D04B6D6211558B0006218A4 /* AccessibilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D04B6D5211558B0006218A4 /* AccessibilityViewController.swift */; };
1314
3D04B6D921155942006218A4 /* LabelAccessibilityPropertiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D04B6D821155942006218A4 /* LabelAccessibilityPropertiesViewController.swift */; };
@@ -79,6 +80,7 @@
7980
/* Begin PBXFileReference section */
8081
0BFCB4FD6BC17AB232B26E72 /* Pods_UnitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_UnitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8182
1104A8CE2B580AC500B6715F /* SwiftUITextEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUITextEntry.swift; sourceTree = "<group>"; };
83+
1104A8D02B595FF600B6715F /* TextInputsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextInputsViewController.swift; sourceTree = "<group>"; };
8284
1635CE4D251EAC6700907101 /* SnapshotTestingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotTestingTests.swift; sourceTree = "<group>"; };
8385
358D84DCD315110A89BD052E /* Pods-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.debug.xcconfig"; sourceTree = "<group>"; };
8486
3A3192D7B9B16BD10FB517A2 /* Pods_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SnapshotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -201,6 +203,7 @@
201203
3DBAC2902242F9B200EF4D0A /* LandmarkContainerViewController.swift */,
202204
3D3F2E132263E6B900F7608E /* InvertColorsViewController.swift */,
203205
3DDE7FF524C6D6BF00999ABA /* AccessibilityCustomActionsViewController.swift */,
206+
1104A8D02B595FF600B6715F /* TextInputsViewController.swift */,
204207
);
205208
name = "Accessibility Screens";
206209
sourceTree = "<group>";
@@ -622,6 +625,7 @@
622625
3D04B6D921155942006218A4 /* LabelAccessibilityPropertiesViewController.swift in Sources */,
623626
3DA12A3222405B9E00EB3C33 /* DataTableViewController.swift in Sources */,
624627
3DEBF24E221018610065424F /* DefaultControlsViewController.swift in Sources */,
628+
1104A8D12B595FF600B6715F /* TextInputsViewController.swift in Sources */,
625629
3FEF854F253846420072611F /* SwiftUIViewWithScrollView.swift in Sources */,
626630
3DF464FE220D594E0048D446 /* ElementSelectionViewController.swift in Sources */,
627631
3DC488372212A7D4006D1E15 /* ModalAccessibilityViewController.swift in Sources */,

Example/AccessibilitySnapshot/RootViewController.swift

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// limitations under the License.
1515
//
1616

17+
import SwiftUI
1718
import UIKit
1819

1920
final class RootViewController: UITableViewController {
@@ -61,6 +62,8 @@ final class RootViewController: UITableViewController {
6162
("Landmark Container", { _ in return LandmarkContainerViewController() }),
6263
("Invert Colors", { _ in return InvertColorsViewController() }),
6364
("User Input Labels", { _ in return UserInputLabelsViewController() }),
65+
("Text Entry", { _ in return TextInputsViewController() }),
66+
("SwiftUI Text Entry", { _ in return UIHostingController(rootView: SwiftUITextEntry()) }),
6467
]
6568

6669
super.init(nibName: nil, bundle: nil)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//
2+
// Copyright 2021 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 TextInputsViewController: AccessibilityViewController {
21+
22+
// MARK: - Private Properties
23+
24+
private let textFieldEmpty: UITextField = .init()
25+
26+
private let textFieldWithPlaceholder: UITextField = .init()
27+
28+
private let textFieldWithText: UITextField = .init()
29+
30+
private let textViewEmpty: UITextView = .init()
31+
32+
private let textViewWithText: UITextView = .init()
33+
34+
private var textInputViews: [UIView] {
35+
return [
36+
textFieldEmpty,
37+
textFieldWithPlaceholder,
38+
textFieldWithText,
39+
textViewEmpty,
40+
textViewWithText,
41+
]
42+
}
43+
44+
// MARK: - UIViewController
45+
46+
override func viewDidLoad() {
47+
super.viewDidLoad()
48+
49+
textFieldWithPlaceholder.placeholder = "Some placeholder text"
50+
51+
textFieldWithText.text = "Hello from Text Field"
52+
53+
textViewWithText.text = "Hello from Text View"
54+
55+
textInputViews.forEach {
56+
$0.layer.borderWidth = 1.0
57+
$0.layer.borderColor = UIColor.lightGray.cgColor
58+
view.addSubview($0)
59+
}
60+
}
61+
62+
override func viewDidLayoutSubviews() {
63+
super.viewDidLayoutSubviews()
64+
65+
textInputViews.forEach { $0.frame.size = CGSize(width: 250, height: 30) }
66+
67+
let statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
68+
69+
var distributionSpecifiers: [ViewDistributionSpecifying] = [ statusBarHeight.fixed, 1.flexible ]
70+
for subview in textInputViews {
71+
distributionSpecifiers.append(subview)
72+
distributionSpecifiers.append(1.flexible)
73+
}
74+
view.applyVerticalSubviewDistribution(distributionSpecifiers)
75+
76+
textViewWithText.accessibilityFrame = textViewWithText.frame
77+
}
78+
79+
}

Example/SnapshotTests/SnapshotTestingTests.swift

+13-2
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,20 @@ final class SnapshotTestingTests: XCTestCase {
138138
assertSnapshot(matching: viewController, as: .imageWithSmartInvert, named: nameForDevice())
139139
}
140140

141-
func testTextEntry() {
141+
func testUIKitTextEntry() {
142+
let viewController = TextInputsViewController()
143+
viewController.view.frame = UIScreen.main.bounds
144+
145+
assertSnapshot(
146+
matching: viewController,
147+
as: .accessibilityImage,
148+
named: nameForDevice()
149+
)
150+
}
151+
152+
func testSwiftUITextEntry() {
142153
let view = SwiftUITextEntry()
143-
.frame(width: 400, height: 400)
154+
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
144155

145156
assertSnapshot(
146157
matching: view,

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

+11-12
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,12 @@ extension NSObject {
134134

135135
if accessibilityTraits.contains(.textEntry) {
136136
if accessibilityTraits.contains(.scrollable) {
137-
// This is being a UITextView/TextEditor
138-
if let accessibilityValue = accessibilityValue, !accessibilityValue.isEmpty {
139-
// No-op. iOS does not read the trait name when there's text.
140-
} else {
141-
traitSpecifiers.append(strings.textEntryTraitName)
142-
}
137+
// This is a UITextView/TextEditor
143138
} else {
144139
// This is a UITextField/TextField
145-
traitSpecifiers.append(strings.textEntryTraitName)
146140
}
141+
142+
traitSpecifiers.append(strings.textEntryTraitName)
147143
}
148144

149145
if accessibilityTraits.contains(.header) {
@@ -246,11 +242,7 @@ extension NSObject {
246242
if accessibilityTraits.contains(.textEntry) && !accessibilityTraits.contains(.notEnabled) {
247243
if accessibilityTraits.contains(.scrollable) {
248244
// This is a UITextView/TextEditor
249-
if let accessibilityValue = accessibilityValue, !accessibilityValue.isEmpty {
250-
// No-op. iOS does not read the hint when there's text.
251-
} else {
252-
hintDescription = strings.textEntryTraitHint
253-
}
245+
hintDescription = strings.scrollableTextEntryTraitHint
254246
} else {
255247
// This is a UITextField/TextField
256248
hintDescription = strings.textEntryTraitHint
@@ -370,6 +362,8 @@ extension NSObject {
370362

371363
let textEntryTraitHint: String
372364

365+
let scrollableTextEntryTraitHint: String
366+
373367
// MARK: - Life Cycle
374368

375369
init(locale: String?) {
@@ -521,6 +515,11 @@ extension NSObject {
521515
comment: "Hint describing how to use elements with the 'text entry' accessibility trait",
522516
locale: locale
523517
)
518+
self.scrollableTextEntryTraitHint = "Double tap to edit., Use the rotor to access Misspelled Words".localized(
519+
key: "trait.scrollable_text_field.hint",
520+
comment: "Hint describing how to use elements with the 'text entry' and 'scrollable' accessibility traits",
521+
locale: locale
522+
)
524523
}
525524

526525
}

0 commit comments

Comments
 (0)