From c6584b4b262591daa84973e1b38dca1e9d4d503e Mon Sep 17 00:00:00 2001 From: Giovani Pereira Date: Thu, 29 Sep 2022 14:19:47 -0300 Subject: [PATCH 1/2] Created dismiss gesture visualization --- .../project.pbxproj | 8 + .../ContentHierarchySection.swift | 3 +- .../ContentHierarchy/Pages/DismissPage.swift | 22 ++ .../ContentHierarchy/Pages/GroupingPage.swift | 2 +- .../UsingTheVoiceOver/GesturesPage.swift | 5 + Accessibility Handbook/Strings/Strings.swift | 6 + .../Strings/en.lproj/Localizable.strings | 2 + .../Strings/pt-BR.lproj/Localizable.strings | 2 + .../UI/Gestures/DismissGesture.swift | 209 ++++++++++++++++++ 9 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift create mode 100644 Accessibility Handbook/UI/Gestures/DismissGesture.swift diff --git a/Accessibility Handbook.xcodeproj/project.pbxproj b/Accessibility Handbook.xcodeproj/project.pbxproj index deef83f..490f4b4 100644 --- a/Accessibility Handbook.xcodeproj/project.pbxproj +++ b/Accessibility Handbook.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 3F25391328DBE05A00B089EA /* CircularProgressionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F25391228DBE05A00B089EA /* CircularProgressionView.swift */; }; 3F41C11728E49CBB0092CF28 /* UIFontMetricsPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F41C11628E49CBB0092CF28 /* UIFontMetricsPage.swift */; }; 3F41C11928E4A4BB0092CF28 /* AdjustLayoutToScaledFontPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F41C11828E4A4BB0092CF28 /* AdjustLayoutToScaledFontPage.swift */; }; + 3F41C11B28E5F0D60092CF28 /* DismissPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F41C11A28E5F0D60092CF28 /* DismissPage.swift */; }; + 3F41C11D28E5FC980092CF28 /* DismissGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F41C11C28E5FC980092CF28 /* DismissGesture.swift */; }; 3F41DB0E28E2553E00E0B056 /* HorizontalSwipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F41DB0D28E2553E00E0B056 /* HorizontalSwipe.swift */; }; 3F4E7F8828DC97E100710F18 /* ContentHierarchySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F4E7F8728DC97E100710F18 /* ContentHierarchySection.swift */; }; 3F4E7F8B28DC980700710F18 /* ModalViewPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F4E7F8A28DC980700710F18 /* ModalViewPage.swift */; }; @@ -131,6 +133,8 @@ 3F25391228DBE05A00B089EA /* CircularProgressionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressionView.swift; sourceTree = ""; }; 3F41C11628E49CBB0092CF28 /* UIFontMetricsPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFontMetricsPage.swift; sourceTree = ""; }; 3F41C11828E4A4BB0092CF28 /* AdjustLayoutToScaledFontPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjustLayoutToScaledFontPage.swift; sourceTree = ""; }; + 3F41C11A28E5F0D60092CF28 /* DismissPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissPage.swift; sourceTree = ""; }; + 3F41C11C28E5FC980092CF28 /* DismissGesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissGesture.swift; sourceTree = ""; }; 3F41DB0D28E2553E00E0B056 /* HorizontalSwipe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalSwipe.swift; sourceTree = ""; }; 3F4E7F8728DC97E100710F18 /* ContentHierarchySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentHierarchySection.swift; sourceTree = ""; }; 3F4E7F8A28DC980700710F18 /* ModalViewPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalViewPage.swift; sourceTree = ""; }; @@ -264,6 +268,7 @@ 3FC3E5EE28E3334A00B7C0D7 /* MultiTap.swift */, 3F6C5AB928E3748A00B12065 /* MultiFingerSwipe.swift */, 3F6C5ABB28E37FED00B12065 /* MultiFingerTap.swift */, + 3F41C11C28E5FC980092CF28 /* DismissGesture.swift */, ); path = Gestures; sourceTree = ""; @@ -282,6 +287,7 @@ children = ( 3F4E7F8A28DC980700710F18 /* ModalViewPage.swift */, 3F4E7F8C28DC981700710F18 /* GroupingPage.swift */, + 3F41C11A28E5F0D60092CF28 /* DismissPage.swift */, ); path = Pages; sourceTree = ""; @@ -801,6 +807,7 @@ 3FF4A29128DF540D005D291A /* SyntaxHighlight.swift in Sources */, 3FBF058F28DA9E3E00DA5BF5 /* ActivatePage.swift in Sources */, 3F4E7F9128DCA6AC00710F18 /* ChangeCursorPositionPage.swift in Sources */, + 3F41C11B28E5F0D60092CF28 /* DismissPage.swift in Sources */, 3FC73ECE28DDDFB900D89F64 /* TheUpsideDown.swift in Sources */, 3F25390F28DBCF1200B089EA /* SecretActions.swift in Sources */, 3FBF059128DA9E4600DA5BF5 /* LongPressPage.swift in Sources */, @@ -822,6 +829,7 @@ 3FBF05E628DB639300DA5BF5 /* InvertColorsPage.swift in Sources */, 3F6C5ABC28E37FED00B12065 /* MultiFingerTap.swift in Sources */, 3FBF05E428DB602000DA5BF5 /* NotifyScreenChangesPage.swift in Sources */, + 3F41C11D28E5FC980092CF28 /* DismissGesture.swift in Sources */, 3FF4A29D28DF93F3005D291A /* String+Extensions.swift in Sources */, 3FBF05A228DAB94800DA5BF5 /* GameCell.swift in Sources */, 3FBF059528DA9E5500DA5BF5 /* CustomActionsPage.swift in Sources */, diff --git a/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/ContentHierarchySection.swift b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/ContentHierarchySection.swift index a219214..96b7bfe 100644 --- a/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/ContentHierarchySection.swift +++ b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/ContentHierarchySection.swift @@ -11,6 +11,7 @@ struct ContentHierarchySectionSection: Section { let title: String = L10n.contentHiererachy let pages: [Page] = [ ModalViewPage(), - GroupingPage() + GroupingPage(), + DismissPage() ] } diff --git a/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift new file mode 100644 index 0000000..3073441 --- /dev/null +++ b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift @@ -0,0 +1,22 @@ +// +// DismissPage.swift +// Accessibility Handbook +// +// Created by Giovani Nascimento Pereira on 29/09/22. +// + +import SwiftUI + +struct DismissPage: View, Page { + let title: String = "" + + var body: some View { + PageContent(next: nil) { + Group { + DismissGesture() + .frame(width: nil, height: 100.0) + } + .toAny() + } + } +} diff --git a/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/GroupingPage.swift b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/GroupingPage.swift index 1faac43..68561af 100644 --- a/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/GroupingPage.swift +++ b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/GroupingPage.swift @@ -11,7 +11,7 @@ struct GroupingPage: View, Page { let title: String = L10n.Grouping.title var body: some View { - PageContent(next: nil) { + PageContent(next: DismissPage()) { Group { content VerticalSpace(.large) diff --git a/Accessibility Handbook/Book/VoiceOverGuide/UsingTheVoiceOver/GesturesPage.swift b/Accessibility Handbook/Book/VoiceOverGuide/UsingTheVoiceOver/GesturesPage.swift index 413a2b0..3985ccb 100644 --- a/Accessibility Handbook/Book/VoiceOverGuide/UsingTheVoiceOver/GesturesPage.swift +++ b/Accessibility Handbook/Book/VoiceOverGuide/UsingTheVoiceOver/GesturesPage.swift @@ -67,6 +67,11 @@ private extension GesturesPage { animation: ThreeFingerSwipeDown().toAny(), description: L10n.Gestures.ThreeFingersSwipeDown.description ) + item( + title: L10n.Gesture.dismiss, + animation: DismissGesture().toAny(), + description: L10n.Gestures.Dismiss.description + ) } } diff --git a/Accessibility Handbook/Strings/Strings.swift b/Accessibility Handbook/Strings/Strings.swift index b5c5702..b4fa8f7 100644 --- a/Accessibility Handbook/Strings/Strings.swift +++ b/Accessibility Handbook/Strings/Strings.swift @@ -893,6 +893,8 @@ internal enum L10n { internal static func accessible(_ p1: Any) -> String { return L10n.tr("Localizable", "Gesture.accessible", String(describing: p1)) } + /// 'Z' with 2 fingers. + internal static let dismiss = L10n.tr("Localizable", "Gesture.dismiss") /// Double Tap internal static let doubleTap = L10n.tr("Localizable", "Gesture.doubleTap") /// Four fingers double tap. @@ -942,6 +944,10 @@ internal enum L10n { internal static let text1 = L10n.tr("Localizable", "Gestures.text1") /// Gestures Guide internal static let title = L10n.tr("Localizable", "Gestures.title") + internal enum Dismiss { + /// Gesture to dismiss modals and pop to preview view on navigation stack. + internal static let description = L10n.tr("Localizable", "Gestures.dismiss.description") + } internal enum DoubleTap { /// Activate element, the same as tapping it when the VoicOver is disabled. internal static let description = L10n.tr("Localizable", "Gestures.doubleTap.description") diff --git a/Accessibility Handbook/Strings/en.lproj/Localizable.strings b/Accessibility Handbook/Strings/en.lproj/Localizable.strings index f3f6f4a..ba698b4 100644 --- a/Accessibility Handbook/Strings/en.lproj/Localizable.strings +++ b/Accessibility Handbook/Strings/en.lproj/Localizable.strings @@ -777,6 +777,7 @@ "Gestures.fourFingersDoubleTap.description" = "Start/Stop gesture helper. When enabled, it will tell every gesture performed and what it does."; "Gestures.helper" = "Gesture Helper"; "Gestures.reading" = "Reading"; +"Gestures.dismiss.description" = "Gesture to dismiss modals and pop to preview view on navigation stack."; "Gesture.swipeRight" = "Swipe Right"; "Gesture.swipeLeft" = "Swipe Left"; @@ -797,6 +798,7 @@ "Gesture.threeFingersDoubleTap" = "Three fingers double tap"; "Gesture.threeFingersTripleTap" = "Three fingers triple tap"; "Gesture.fourFingersDoubleTap" = "Four fingers double tap."; +"Gesture.dismiss" = "'Z' with 2 fingers."; "Gesture.accessible" = "Animation representing the gesture for %@"; diff --git a/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings b/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings index 53e10fd..3f2636a 100644 --- a/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings +++ b/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings @@ -777,6 +777,7 @@ "Gestures.fourFingersDoubleTap.description" = "Ajuda de Gestos. Quando ativo, irá descrever cada gesto performado."; "Gestures.helper" = "Ajuda de gestos"; "Gestures.reading" = "Leitura"; +"Gestures.dismiss.description" = "Gesto de fechar conteúdo. Fecha modais ou volta pra página anterior na navegação."; "Gesture.swipeRight" = "Swipe para direita"; "Gesture.swipeLeft" = "Swipe para esquerda"; @@ -797,6 +798,7 @@ "Gesture.threeFingersDoubleTap" = "Toque duplo com 3 dedos"; "Gesture.threeFingersTripleTap" = "Toque triplo com 3 dedos"; "Gesture.fourFingersDoubleTap" = "Toque duplo com 4 dedos"; +"Gesture.dismiss" = "'Z' with 2 fingers."; "Gesture.accessible" = "Animation representing the gesture for %@"; diff --git a/Accessibility Handbook/UI/Gestures/DismissGesture.swift b/Accessibility Handbook/UI/Gestures/DismissGesture.swift new file mode 100644 index 0000000..94fa47c --- /dev/null +++ b/Accessibility Handbook/UI/Gestures/DismissGesture.swift @@ -0,0 +1,209 @@ +// +// DismissGesture.swift +// Accessibility Handbook +// +// Created by Giovani Nascimento Pereira on 29/09/22. +// + +import SwiftUI + +struct DismissGesture: UIViewRepresentable { + func makeUIView(context: Context) -> UIView { + let animation = DismissGestureView() + return animation + } + + func updateUIView(_ animation: UIView, context: Context) { + (animation as? DismissGestureView)?.start() + } +} + +// - UIKit animation + +final private class DismissGestureView: UIView { + private enum Constants { + static let initialOffset: CGFloat = -50 + static let finalOffset: CGFloat = 50 + static let initialSize: CGFloat = 30.0 + static let spacing: CGFloat = 33.0 + } + + private let gesture: UIView = { + let view = UIView() + view.backgroundColor = .label + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private let secondFinger: UIView = { + let view = UIView() + view.backgroundColor = .label + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + // MARK: - Animatable + private var widthConstraint: NSLayoutConstraint? + private var secondWidthConstraint: NSLayoutConstraint? + private var horizontalOffset: NSLayoutConstraint? + private var secondHorizontalOffset: NSLayoutConstraint? + private var verticalOffset: NSLayoutConstraint? + private var secondVerticalOffset: NSLayoutConstraint? + + init() { + super.init(frame: .zero) + setup() + } + + required init?(coder: NSCoder) { fatalError() } + + func start() { + reset() + } +} + +// MARK: - Setup + +private extension DismissGestureView { + func setup() { + setupHierarchy() + setupConstraints() + setupAccessibility() + } + + func setupHierarchy() { + addSubview(gesture) + addSubview(secondFinger) + } + + func setupConstraints() { + constrainGesture() + constrainSecondFinger() + } + + func setupAccessibility() { + isAccessibilityElement = true + subviews.forEach { $0.isAccessibilityElement = false } + accessibilityLabel = L10n.Gesture.accessible(L10n.Gesture.dismiss) + } + + private func constrainGesture() { + widthConstraint = gesture.widthAnchor.constraint(equalToConstant: .zero) + horizontalOffset = gesture.centerXAnchor.constraint(equalTo: centerXAnchor, constant: Constants.initialOffset) + verticalOffset = gesture.centerYAnchor.constraint(equalTo: centerYAnchor, constant: Constants.initialOffset) + + NSLayoutConstraint.activate([ + widthConstraint, + horizontalOffset, + verticalOffset, + gesture.heightAnchor.constraint(equalTo: gesture.widthAnchor) + ].compactMap { $0 }) + } + + private func constrainSecondFinger() { + secondWidthConstraint = secondFinger.widthAnchor.constraint(equalToConstant: .zero) + secondHorizontalOffset = secondFinger.centerXAnchor.constraint(equalTo: centerXAnchor, constant: Constants.initialOffset) + secondVerticalOffset = secondFinger.centerYAnchor.constraint(equalTo: centerYAnchor, constant: Constants.initialOffset) + + NSLayoutConstraint.activate([ + secondWidthConstraint, + secondVerticalOffset, + secondHorizontalOffset, + secondFinger.heightAnchor.constraint(equalTo: secondFinger.widthAnchor), + ].compactMap { $0 }) + } +} + +// MARK: - Animation + +private extension DismissGestureView { + func popUp() { + UIView.animate(withDuration: 0.2, delay: 0.5, options: [.curveEaseIn]) { + self.widthConstraint?.constant = Constants.initialSize + self.gesture.layer.cornerRadius = Constants.initialSize / 2.0 + + self.secondWidthConstraint?.constant = Constants.initialSize + self.secondFinger.layer.cornerRadius = Constants.initialSize / 2.0 + + self.layoutIfNeeded() + } completion: { _ in + self.slideRight() + } + } + + func slideRight() { + UIView.animate(withDuration: 0.7, delay: .zero, options: [.curveEaseInOut]) { + self.gesture.layer.cornerRadius = 13.0 + self.horizontalOffset?.constant = Constants.finalOffset + self.widthConstraint?.constant = 26.0 + self.gesture.alpha = 0.9 + + self.secondFinger.layer.cornerRadius = 13.0 + self.secondHorizontalOffset?.constant = Constants.finalOffset + Constants.spacing + self.secondWidthConstraint?.constant = 26.0 + self.secondFinger.alpha = 0.9 + + self.layoutIfNeeded() + } completion: { _ in + self.slideDown() + } + } + + func slideDown() { + UIView.animate(withDuration: 0.7, delay: .zero, options: [.curveEaseInOut]) { + self.horizontalOffset?.constant = Constants.initialOffset + self.verticalOffset?.constant = Constants.finalOffset + self.widthConstraint?.constant = 24.0 + self.gesture.layer.cornerRadius = 12.0 + self.gesture.alpha = 0.8 + + self.secondHorizontalOffset?.constant = Constants.initialOffset + Constants.spacing + self.secondVerticalOffset?.constant = Constants.finalOffset + self.secondWidthConstraint?.constant = 24.0 + self.secondFinger.layer.cornerRadius = 12.0 + self.secondFinger.alpha = 0.8 + + self.layoutIfNeeded() + } completion: { _ in + self.slideRightAgain() + } + } + + func slideRightAgain() { + UIView.animate(withDuration: 0.7, delay: .zero, options: [.curveEaseInOut]) { + self.horizontalOffset?.constant = Constants.finalOffset + self.widthConstraint?.constant = 20.0 + self.gesture.layer.cornerRadius = 10.0 + + self.secondHorizontalOffset?.constant = Constants.finalOffset + Constants.spacing + self.secondWidthConstraint?.constant = 20.0 + self.secondFinger.layer.cornerRadius = 10.0 + + self.layoutIfNeeded() + } completion: { _ in + self.reset() + } + } + + func reset() { + UIView.animate(withDuration: 0.2, delay: .zero, options: [.curveEaseOut]) { + self.widthConstraint?.constant = .zero + self.gesture.layer.cornerRadius = .zero + + self.secondWidthConstraint?.constant = .zero + self.secondFinger.layer.cornerRadius = .zero + + self.layoutIfNeeded() + } completion: { _ in + self.horizontalOffset?.constant = Constants.initialOffset + self.verticalOffset?.constant = Constants.initialOffset + self.gesture.alpha = 1.0 + + self.secondHorizontalOffset?.constant = Constants.initialOffset + Constants.spacing + self.secondVerticalOffset?.constant = Constants.initialOffset + self.secondFinger.alpha = 1.0 + self.layoutIfNeeded() + self.popUp() + } + } +} From d97669bd27cdf3f4f1fbdd130121c1bd29449d44 Mon Sep 17 00:00:00 2001 From: Giovani Pereira Date: Thu, 29 Sep 2022 14:43:44 -0300 Subject: [PATCH 2/2] Add escape gesture doc --- .../ContentHierarchy/Pages/DismissPage.swift | 45 +++++++++++++++++-- Accessibility Handbook/Strings/Strings.swift | 15 +++++++ .../Strings/en.lproj/Localizable.strings | 9 ++++ .../Strings/pt-BR.lproj/Localizable.strings | 9 ++++ 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift index 3073441..483a180 100644 --- a/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift +++ b/Accessibility Handbook/Book/VoiceOverGuide/ContentHierarchy/Pages/DismissPage.swift @@ -8,15 +8,54 @@ import SwiftUI struct DismissPage: View, Page { - let title: String = "" + let title: String = L10n.DismissPage.title var body: some View { PageContent(next: nil) { Group { - DismissGesture() - .frame(width: nil, height: 100.0) + intro + handling } .toAny() } } } + +private extension DismissPage { + var intro: some View { + Group { + Text(L10n.DismissPage.text1) + VerticalSpace(.regular) + DismissGesture() + .frame(width: nil, height: 100.0) + VerticalSpace(.regular) + Comment(L10n.DismissPage.comment1) + InternalLink(page: GesturesPage().page, title: L10n.Navigation.gesturesLink) + } + } + + var handling: some View { + Group { + Text(L10n.DismissPage.Handle.text1) + Code.uikit( + """ + override func accessibilityPerformEscape() -> Bool { + // Handle escape + // Returns true if the content was dismissed + return true + } + """ + ) + Text(L10n.DismissPage.Handle.text2) + Code.swiftUI( + """ + View() + .accessibilityAction(.escape) { + // Handle escape + } + """ + ) + DocButton(link: "https://developer.apple.com/documentation/objectivec/nsobject/1615091-accessibilityperformescape", title: title) + } + } +} diff --git a/Accessibility Handbook/Strings/Strings.swift b/Accessibility Handbook/Strings/Strings.swift index b4fa8f7..b5dea8d 100644 --- a/Accessibility Handbook/Strings/Strings.swift +++ b/Accessibility Handbook/Strings/Strings.swift @@ -793,6 +793,21 @@ internal enum L10n { } } + internal enum DismissPage { + /// Try it out! Enable the VoiceOver and perform a 'Z' with 2 fingers. + internal static let comment1 = L10n.tr("Localizable", "DismissPage.comment1") + /// The VoiceOver has a dedicated 'dismiss gesture', the Escape, which is used to close modals or pop the current view on the navigation stack. + internal static let text1 = L10n.tr("Localizable", "DismissPage.text1") + /// Escape + internal static let title = L10n.tr("Localizable", "DismissPage.title") + internal enum Handle { + /// On UIKit, you can add a custom handling to this gesture by implementing the 'perform escape' method. + internal static let text1 = L10n.tr("Localizable", "DismissPage.Handle.text1") + /// On SwiftUI, it's the same as adding a 'Magic Tap' action, but using the escape type. + internal static let text2 = L10n.tr("Localizable", "DismissPage.Handle.text2") + } + } + internal enum DynamicFonts { /// Implementing Dynamic Fonts internal static let implementing = L10n.tr("Localizable", "DynamicFonts.implementing") diff --git a/Accessibility Handbook/Strings/en.lproj/Localizable.strings b/Accessibility Handbook/Strings/en.lproj/Localizable.strings index ba698b4..ad6d7ee 100644 --- a/Accessibility Handbook/Strings/en.lproj/Localizable.strings +++ b/Accessibility Handbook/Strings/en.lproj/Localizable.strings @@ -892,3 +892,12 @@ "AdjustLayoutToScaledFontPage.Example.title" = "Content title"; "AdjustLayoutToScaledFontPage.Example.body" = "Content body some content"; "AdjustLayoutToScaledFontPage.Example.description" = "Content description"; + +// Dismiss + +"DismissPage.title" = "Escape"; +"DismissPage.text1" = "The VoiceOver has a dedicated 'dismiss gesture', the Escape, which is used to close modals or pop the current view on the navigation stack."; +"DismissPage.comment1" = "Try it out! Enable the VoiceOver and perform a 'Z' with 2 fingers."; + +"DismissPage.Handle.text1" = "On UIKit, you can add a custom handling to this gesture by implementing the 'perform escape' method."; +"DismissPage.Handle.text2" = "On SwiftUI, it's the same as adding a 'Magic Tap' action, but using the escape type."; diff --git a/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings b/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings index 3f2636a..eede438 100644 --- a/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings +++ b/Accessibility Handbook/Strings/pt-BR.lproj/Localizable.strings @@ -892,3 +892,12 @@ "AdjustLayoutToScaledFontPage.Example.title" = "Título do conteúdo"; "AdjustLayoutToScaledFontPage.Example.body" = "Corpo do texto com mais conteúdo"; "AdjustLayoutToScaledFontPage.Example.description" = "Descrição aqui embaixo"; + +// Dismiss + +"DismissPage.title" = "Escape"; +"DismissPage.text1" = "O VoiceOver tem um gesto dedicado para fechar Modais e outros conteúdos: O 'Ecape'."; +"DismissPage.comment1" = "Você pode tentar executar esse gesto aqui mesmo! Faça um 'Z' com 2 dedos na tela."; + +"DismissPage.Handle.text1" = "No UIKit, você pode adicionar um tratamento customizado implementando o método de 'perform escape'."; +"DismissPage.Handle.text2" = "Já em SwiftUI, é a mesma maneira de adicionar um 'Magic Tap', mas usando o tipo `escape`.";