前言
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
管理焦點的方法。