Accessibility

  • 关于SwiftUI的Accessibility
  • 怎么将DynamicType与自定义Font一同运用
  • 怎么指定视图支撑的动态类型的巨细
  • 怎么检测“reduce motion”的相关功用设置
  • 怎么检测深色形式
  • 怎么运用装修图画来削减屏幕阅览器的混乱
  • 怎么依据需求削减动画
  • 怎么让VoiceOver独自朗诵字符

概述

文章首要共享SwiftUI Modifier的学习进程,将运用事例的方法进行说明。内容浅显易懂,Accessibility未调试,不过测验代码是完全的。假如想要运行结果,能够移步Github下载code -> github事例链接

1、关于SwiftUI的Accessibility

默许情况下,SwiftUI应用程序具有十分高的可拜访性,除非主动更改默许设置。这种行为的关键是SwiftUI布局是基于Stack的方法。将视图放在Hstack和VStack中,全部都有默许的顺序,因而体系能够大致了解布局应该怎么设定。相比之下,UIKit和AutoLayout能够将视图放在任何地方,因而体系有必要有用的对视图应该怎么排序做出最佳猜测。

SwiftUI还建议咱们为一切的交互增加标签,明确用途。可是,咱们能够屏蔽标签,以及它们被隐藏,体系仍然会运用它们作为屏幕阅览器的音频提示。因而,SwiftUI供给了许多的可拜访性。可是,还有额外的工具来更好的体会来解决下面的问题:

  • 屏幕阅览器应该怎么阅览内容?
  • 是否一切内容都需求阅览?
  • 假如用户不喜爱杂乱的动画怎么办?

2、怎么将DynamicType与自定义Font一同运用

假如在iOS14或更高的版别,就能够实现主动移Font的主动缩放。可是,假如需求字体相关于特定动态类型进行缩放,则运用relativeTo修饰符。

struct FFFontDynamicType: View {
    var body: some View {
        //使字体从24pt开端,但它会相关于Headline DynamicType字体进行缩放。
        Text("meta BBLv")
            .font(.custom("Georgia", size: 24, relativeTo: .headline))
        //假如想禁用字体的动态类型,运用fixedSize修饰符字体巨细,不管动态类型怎么设置都不会影响字体巨细
        Text("metabblv@163.com")
            .font(.custom("Georgia", fixedSize: 24))
    }
}

3、怎么指定视图支撑的动态类型的巨细

SwiftUI对动态类型的主动支撑意味着视图能够依据用户的偏好扩大或缩小。可是,一些情况下会超出屏幕导致UI的不一致,能够运用dyanmicTypeSize()来约束。

struct FFSpecifyDynamicType: View {
    var body: some View {
        VStack {
            //与固定值一同运用,意味着视图将疏忽一切动态类型的巨细
            Text("This will stay small")
                .dynamicTypeSize(.xxLarge)
            //能够指定规模
            Text("This won't go above large")
                .dynamicTypeSize(...DynamicTypeSize.large)
            Text("This will scale within a range")
                .dynamicTypeSize(DynamicTypeSize.large...DynamicTypeSize.xxxLarge)
            Text("This will scale to any Size")
            //许多用户喜爱以来较大的动态字体来运用App。可是,跟着屏幕内信息量的增加,
            //在某些特定的场景下要约束这种特性。
        }
    }
}

4、怎么检测“reduce motion”的相关功用设置

跟着iOS的开展,越来越多的用户对画面更加灵敏、更挑剔,尤其是那些大型或杂乱的动画。因而,iOS有一个名为“reduce motion”的内置辅佐功用设置,应用程序能够读取该设置并依据需求做出响应。现在由需求来决定“reduce motion”的具体含义:

  • 删去动画?
  • 仍是将动画更改为不那么激烈?
  • 是否应该保留一些重要的动画并删去那些视觉吸引力的动画?

例如,假如希望为大多数用户供给弹性动画,但关于想要reduce motion的用户底子不需求动画,怎么设定。

struct FFAccessibilityReduceMotion: View {
    //在SwiftUI中,此设置作为环境的Bool值发布,将其特点增加到视图中
    @Environment(\.accessibilityReduceMotion) var reduceMotion
    @State private var scale = 1.0
    var body: some View {
        VStack {
            Spacer()
            Circle()
                .frame(width: 20, height: 20)
                .scaleEffect(scale)
                .animation(reduceMotion ? nil : .spring(response: 1, dampingFraction: 0.1), value: scale)
            Spacer()
            Button("Increase scale") {
                scale *= 1.5
            }
        }
    }
}

这会创立一个小圆圈,每次按下按钮时都会经过弹簧动画将其扩大。但假如用户启用“reduce motion”,动画将被完全删去。

5、怎么检测深色形式

SwiftUI能够运用环境检测键(colorScheme)检测当时是否启用了深色形式或浅色形式。假如运用了@environment声明了此特点,就能够在视图中引用它,并且当配色计划更改时将主动加载。

struct FFAccessibilityDarkMode: View {
    @Environment(\.colorScheme) var colorScheme
    var body: some View {
        Text(colorScheme == .dark ? "META BBLV in dark mode" : "META BBLV in light mode")
    }
}

6、怎么运用装修图画来削减屏幕阅览器的混乱

SwiftUI会主动运用图画称号作为屏幕阅览器标签,通常情况下会很有用。可是,有些图画并不合适阅览,因为它仅仅装修性的。它们不会传达屏幕其他地方没有的信息,仅仅为了让用户界面看起来更好看。

Image(“star”)这种方法创立的图画,则会将她们作为规范UI的一部分读出。更好的方法是运用Image(decorative:)初始化程序来创立它们,它告知SwiftUI图画不应该暴露给屏幕阅览去器。

struct FFAccessibilityDecorative: View {
    var body: some View {
        Image(decorative: "star")
        //经过这种方法构建的UI,运用VoiceOver检查时,屏幕阅览器是不会读出此标签的。
    }
}

7、怎么依据需求削减动画

SwiftUI的withAnimation()修饰符能够轻松的在视图上履行自定义动画,但它不遵守“reduce mode”辅佐功用的设置。因而关于有特定需求的人来讲,可能不符合需求了。

struct FFAccessibilityReduceModeRequest: View {
    @State private var scale = 1.0
    var body: some View {
        Text("Meta BBLv")
            .scaleEffect(scale)
            .onTapGesture {
                withOptionalAimation {
                    scale *= 1.5
                }
            }
    }
    //假如想要在withAnimation()同时遵守辅佐功用的设置,增加一个大局函数可能是一个有用的解决计划
    func withOptionalAimation<Result>(_ animation: Animation? = .default, _ body: () throws -> Result) rethrows -> Result {
        if UIAccessibility.isReduceMotionEnabled {
            return try body()
        } else {
            return try withAnimation(animation, body)
        }
    }
    //在每次触发动画是,都会主动检查是否启用了“reduce mode”,并为特别请求reducemode的用户来禁用它。
}

8、怎么让VoiceOver独自朗诵字符

大多数的文本都能够作为单词阅览,但某些特殊文本(例如暗码,股票代码和某些特定的数字)有必要经过VoiceOver诸葛字母的阅览才能发挥作用。在SwiftUI中,能够运用speechSpellsOutCharacters()修饰符启用此功用。

struct FFAccessibilityVoiceOver: View {
    var body: some View {
        //当对整组元素启用辅佐功用时,会有更好的结果
        VStack {
            Text("Your password is")
            Text("abCayer-muQai")
                .font(.title)
                .speechSpellsOutCharacters()
        }
        .accessibilityElement(children: .combine)
        //运用该代码,VoiceOver会天然的主动读出“你的暗码是”,然后依据要求拼代码部分。
    }
}

调试意外

我目前的设备情况:

  • macOS:Version 13.4.1 、 Version 14.0 beta 2
  • Xcode:Version 15.0 beta 2 (15A5161b)
  • Simulator iPhone 14 Pro:iOS 17.0 beta 2
  • iPhone 14 Pro:iOS 17.0 beta 6

因为是Accessibility部分调试,涉及到调试中修正控制中心设置问题,所以无法运用模拟器来调试,在真机调试中报出下面的问题:

dyld[5218]: Symbol not found: _$s21DeveloperToolsSupport7PreviewV7SwiftUIE_6traits4bodyACSSSg_AA0D5TraitVyAC10ViewTraitsOGdAD0J0_pyctcfC
  Referenced from: <48CEF6E7-4F6C-3597-9EA3-182CF891DB38> /private/var/containers/Bundle/Application/CBD3CB7C-D7CE-472D-B4BC-46DC960A6B06/FFModifier.app/FFModifier
  Expected in:     <FE724F2F-E9CA-3711-BED5-5124FE98C7C0> /System/Library/Frameworks/SwiftUI.framework/SwiftUI

推测是因为我的iPhone版别与Xcode版别不一致导致的SwiftUI版别不一致问题,所以呈现了“Symbol not found:”。没过于纠结,后面假如能够调试了,我会将图补充的。