前言
SwiftUI Release 引入了強大的新功能,其中之一是輔助焦點管理。
這個新功能使得在SwiftUI中處理輔助技術(如 VoiceOver 和 Switch Control)的焦點狀態變得更加輕鬆。本文將介紹如何使用 @FocusState 屬性包裝器來在SwiftUI中管理和移動輔助焦點。
使用 @FocusState 屬性包裝器
在 SwiftUI Release 中,我們獲得了一整套特殊工具來更有效地處理輔助焦點。其中包括 @FocusState 屬性包裝器和 focused 視圖修飾符。通過使用這些工具,我們能夠以與無輔助技術相同的方式處理輔助焦點。
核心代碼如下:
import SwiftUI
struct SignInView: View {
@FocusState
private var isEmailFocused: Bool
@State private var email = ""
var body: some View {
NavigationView {
Form {
TextField("Email", text: $email, prompt: Text("Enter your email"))
.focused($isEmailFocused)
}
.navigationTitle("Sign In")
.onChange(of: isEmailFocused) { newValue in
print(newValue)
}
}
}
}
如上例所示,我們使用 @FocusState 屬性包裝器定義一個變量,表示 email 字段是否聚焦。SwiftUI 默認使用 false 值初始化該變量,因為用户可以聚焦屏幕的任何其他區域。我們還使用 focused 視圖修飾符將特定視圖的焦點狀態綁定到保存其值的變量。
請記住,您可以聲明盡需要的變量,以使用 @FocusState 屬性包裝器涵蓋輔助焦點邏輯。
高級技巧:專用輔助技術
核心代碼如下:
import SwiftUI
struct SignInView: View {
@FocusState
private var isEmailFocused: Bool
@FocusState
private var isPasswordFocused: Bool
@State private var email = ""
@State private var password = ""
var body: some View {
NavigationView {
Form {
TextField("Email", text: $email, prompt: Text("Enter your email"))
.focused($isEmailFocused)
SecureField("Password", text: $password, prompt: Text("Enter your password"))
.focused($isPasswordFocused)
}
.navigationTitle("Sign In")
}
}
}
@FocusState 屬性包裝器的好處之一是您可以將其行為限制為專用輔助技術。例如,您可以僅為VoiceOver或Switch Control激活 @FocusState 屬性包裝器。默認情況下,SwiftUI 會將設備上可用的所有輔助技術的值進行聚合。
可聚焦字段的高級用法
核心代碼如下:
import SwiftUI
struct SignInView: View {
@FocusState(for: .switchControl)
private var isEmailFocused: Bool
@State private var email = ""
var body: some View {
NavigationView {
Form {
TextField("Email", text: $email, prompt: Text("Enter your email"))
.focused($isEmailFocused)
}
.navigationTitle("Sign In")
.onChange(of: isEmailFocused) { newValue in
print(newValue)
}
}
}
}
如上例所示,我們使用 @FocusState 屬性包裝器為 Switch Control 定義了可選變量 isEmailFocused,以便在用户在視圖之間移動焦點時進行切換。
通常,屏幕上有多個元素,您可能希望在它們之間移動焦點。為了支持這種情況,SwiftUI 提供了一種通過枚舉定義可聚焦字段並在它們之間切換的方法。這種方法是使用 @FocusState 屬性包裝器,併為其提供一個用於標識焦點類型的參數(在此例中是 .switchControl)。
優化體驗
全部代碼如下:
import SwiftUI
enum FocusableField: Hashable {
case email
case password
}
struct ContentView: View {
@State private var email = ""
@State private var password = ""
@FocusState
private var focus: FocusableField?
var body: some View {
NavigationView {
Form {
TextField("email", text: $email, prompt: Text("email"))
.focused($focus, equals: .email)
SecureField("password", text: $password, prompt: Text("password"))
.focused($focus, equals: .password)
Button("login", action: login)
}
.toolbar {
ToolbarItem(placement: .keyboard) {
Button("next") {
if email.isEmpty {
focus = .email
} else if password.isEmpty {
focus = .password
} else {
focus = nil
}
}
}
}
.navigationTitle("Sign in")
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
focus = .email
}
}
}
}
private func login() {
// your logic here
}
}
運行截圖
如上例所示,我們使用了 @FocusState 屬性包裝器與我們的新 FocusableField 枚舉一起使用。該枚舉定義了屏幕上所有可聚焦視圖,應確保 FocusableField 枚舉是可散列的。
使用 @FocusState 屬性包裝器定義了可選變量 focus,以便在用户將焦點從您定義的視圖移動時將其值設置為 nil。
我們還使用了 focused 修飾符的一個版本,將一個視圖綁定到可散列枚舉的特定情況。請記住,您可以通過更改 @FocusState 包裝的變量的值來以編程方式移動 VoiceOver 或 Switch Control 的焦點。
總結
在這篇文章中,我們深入探討了 SwiftUI Release 引入的輔助焦點管理功能,使得處理輔助技術(如 VoiceOver 和 Switch Control)的焦點狀態變得更加輕鬆。通過 @FocusState 屬性包裝器,我們學習瞭如何靈活地管理焦點狀態,以提高用户體驗。通過詳細的示例代碼,我們演示瞭如何在 SwiftUI 中使用 @FocusState,以及如何通過 focused 視圖修飾符將焦點狀態綁定到特定的視圖。此外,我們介紹了一種高級用法,通過枚舉定義可聚焦字段並在它們之間切換,以更好地支持屏幕上多個元素的焦點移動。最後,我們提供了一些優化 SwiftUI 應用的建議,以更好地整合焦點管理,並通過最佳實踐和總結使讀者更深入地瞭解了在 SwiftUI Release 中使用 @FocusState 管理焦點的方法。