Skip to content

Commit

Permalink
Make implementation match VoiceOver
Browse files Browse the repository at this point in the history
  • Loading branch information
David Brunow committed Jan 19, 2024
1 parent cf0c215 commit 8485578
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 13 deletions.
4 changes: 4 additions & 0 deletions Example/AccessibilitySnapshot.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
1104A8CF2B580AC500B6715F /* SwiftUITextEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1104A8CE2B580AC500B6715F /* SwiftUITextEntry.swift */; };
1104A8D12B595FF600B6715F /* TextInputsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1104A8D02B595FF600B6715F /* TextInputsViewController.swift */; };
1635CE4E251EAC6700907101 /* SnapshotTestingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1635CE4D251EAC6700907101 /* SnapshotTestingTests.swift */; };
3D04B6D6211558B0006218A4 /* AccessibilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D04B6D5211558B0006218A4 /* AccessibilityViewController.swift */; };
3D04B6D921155942006218A4 /* LabelAccessibilityPropertiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D04B6D821155942006218A4 /* LabelAccessibilityPropertiesViewController.swift */; };
Expand Down Expand Up @@ -80,6 +81,7 @@
/* Begin PBXFileReference section */
0BFCB4FD6BC17AB232B26E72 /* Pods_UnitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_UnitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1104A8CE2B580AC500B6715F /* SwiftUITextEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUITextEntry.swift; sourceTree = "<group>"; };
1104A8D02B595FF600B6715F /* TextInputsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextInputsViewController.swift; sourceTree = "<group>"; };
1635CE4D251EAC6700907101 /* SnapshotTestingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotTestingTests.swift; sourceTree = "<group>"; };
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>"; };
3A3192D7B9B16BD10FB517A2 /* Pods_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SnapshotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -203,6 +205,7 @@
3DBAC2902242F9B200EF4D0A /* LandmarkContainerViewController.swift */,
3D3F2E132263E6B900F7608E /* InvertColorsViewController.swift */,
3DDE7FF524C6D6BF00999ABA /* AccessibilityCustomActionsViewController.swift */,
1104A8D02B595FF600B6715F /* TextInputsViewController.swift */,
);
name = "Accessibility Screens";
sourceTree = "<group>";
Expand Down Expand Up @@ -625,6 +628,7 @@
3D04B6D921155942006218A4 /* LabelAccessibilityPropertiesViewController.swift in Sources */,
3DA12A3222405B9E00EB3C33 /* DataTableViewController.swift in Sources */,
3DEBF24E221018610065424F /* DefaultControlsViewController.swift in Sources */,
1104A8D12B595FF600B6715F /* TextInputsViewController.swift in Sources */,
3FEF854F253846420072611F /* SwiftUIViewWithScrollView.swift in Sources */,
3DF464FE220D594E0048D446 /* ElementSelectionViewController.swift in Sources */,
3DC488372212A7D4006D1E15 /* ModalAccessibilityViewController.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions Example/AccessibilitySnapshot/RootViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
//

import SwiftUI
import UIKit

final class RootViewController: UITableViewController {
Expand Down Expand Up @@ -61,6 +62,8 @@ final class RootViewController: UITableViewController {
("Landmark Container", { _ in return LandmarkContainerViewController() }),
("Invert Colors", { _ in return InvertColorsViewController() }),
("User Input Labels", { _ in return UserInputLabelsViewController() }),
("Text Entry", { _ in return TextInputsViewController() }),
("SwiftUI Text Entry", { _ in return UIHostingController(rootView: SwiftUITextEntry()) }),
]

super.init(nibName: nil, bundle: nil)
Expand Down
79 changes: 79 additions & 0 deletions Example/AccessibilitySnapshot/TextInputsViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// Copyright 2021 Square Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Paralayout
import UIKit

final class TextInputsViewController: AccessibilityViewController {

// MARK: - Private Properties

private let textFieldEmpty: UITextField = .init()

private let textFieldWithPlaceholder: UITextField = .init()

private let textFieldWithText: UITextField = .init()

private let textViewEmpty: UITextView = .init()

private let textViewWithText: UITextView = .init()

private var textInputViews: [UIView] {
return [
textFieldEmpty,
textFieldWithPlaceholder,
textFieldWithText,
textViewEmpty,
textViewWithText,
]
}

// MARK: - UIViewController

override func viewDidLoad() {
super.viewDidLoad()

textFieldWithPlaceholder.placeholder = "Some placeholder text"

textFieldWithText.text = "Hello from Text Field"

textViewWithText.text = "Hello from Text View"

textInputViews.forEach {
$0.layer.borderWidth = 1.0
$0.layer.borderColor = UIColor.lightGray.cgColor
view.addSubview($0)
}
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

textInputViews.forEach { $0.frame.size = CGSize(width: 250, height: 30) }

let statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0

var distributionSpecifiers: [ViewDistributionSpecifying] = [ statusBarHeight.fixed, 1.flexible ]
for subview in textInputViews {
distributionSpecifiers.append(subview)
distributionSpecifiers.append(1.flexible)
}
view.applyVerticalSubviewDistribution(distributionSpecifiers)

textViewWithText.accessibilityFrame = textViewWithText.frame
}

}
13 changes: 12 additions & 1 deletion Example/SnapshotTests/SnapshotTestingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,20 @@ final class SnapshotTestingTests: XCTestCase {
assertSnapshot(matching: viewController, as: .imageWithHitTargets(), named: nameForDevice())
}

func testUIKitTextEntry() {
let viewController = TextInputsViewController()
viewController.view.frame = UIScreen.main.bounds

assertSnapshot(
matching: viewController,
as: .accessibilityImage,
named: nameForDevice()
)
}

func testTextEntry() {
let view = SwiftUITextEntry()
.frame(width: 400, height: 400)
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

assertSnapshot(
matching: view,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
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 @@ -134,16 +134,12 @@ extension NSObject {

if accessibilityTraits.contains(.textEntry) {
if accessibilityTraits.contains(.scrollable) {
// This is being a UITextView/TextEditor
if let accessibilityValue = accessibilityValue, !accessibilityValue.isEmpty {
// No-op. iOS does not read the trait name when there's text.
} else {
traitSpecifiers.append(strings.textEntryTraitName)
}
// This is a UITextView/TextEditor
} else {
// This is a UITextField/TextField
traitSpecifiers.append(strings.textEntryTraitName)
}

traitSpecifiers.append(strings.textEntryTraitName)
}

if accessibilityTraits.contains(.header) {
Expand Down Expand Up @@ -246,11 +242,7 @@ extension NSObject {
if accessibilityTraits.contains(.textEntry) && !accessibilityTraits.contains(.notEnabled) {
if accessibilityTraits.contains(.scrollable) {
// This is a UITextView/TextEditor
if let accessibilityValue = accessibilityValue, !accessibilityValue.isEmpty {
// No-op. iOS does not read the hint when there's text.
} else {
hintDescription = strings.textEntryTraitHint
}
hintDescription = strings.scrollableTextEntryTraitHint
} else {
// This is a UITextField/TextField
hintDescription = strings.textEntryTraitHint
Expand Down Expand Up @@ -370,6 +362,8 @@ extension NSObject {

let textEntryTraitHint: String

let scrollableTextEntryTraitHint: String

// MARK: - Life Cycle

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

}
Expand Down

0 comments on commit 8485578

Please sign in to comment.