動態

詳情 返回 返回

SwiftUI Release 引入的輔助焦點管理 - 動態 詳情

前言

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

Add a new 評論

Some HTML is okay.