这篇文章介绍了 SwiftUI 中的 FocusState 属性包装器,它允许我们读取和写入视图层次结构中的当前焦点位置。作者演示了如何使用 FocusState 属性包装器和聚焦视图修饰符在 SwiftUI 应用程序中管理焦点,并给出了多个输入框的焦点判断的例子。同时,作者还介绍了如何使用符合 Hashable 协议的枚举类型对聚焦状态进行建模。
此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结
投诉
本文为翻译内容,来自swiftwithmajid
翻译:张洪Heo
推荐访问原文地址:立即访问
SwiftUI 在上次 WWDC 期间变得非常强大。我们获得了许多新功能,其中之一是全新的FocusState属性包装器。FocusState属性包装器允许我们读取和写入视图层次结构中的当前焦点位置。本周我们将学习如何使用FocusState属性包装器和聚焦视图修饰符在 SwiftUI 应用程序中管理焦点。
关于FocusState
SwiftUI 提供了一个新的FocusState属性包装器,适用于所有 Apple 平台,并允许我们专注于特定视图或检查该视图是否已经获得焦点。使用起来毫不费力。让我们看看如何使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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("email")) .focused($isEmailFocused) } .navigationTitle("Sign in") .onChange(of: isEmailFocused) { newValue in print(newValue) } } } }
|
焦点绑定
正如你在上面的示例中看到的,我们需要使用FocusState属性包装器定义一个布尔变量。我们也有它的价值结合使用特定视图的焦点状态集中视图调节。一旦用户关注它,SwiftUI 就会将视图的布尔值设置为 true。一旦视图失去焦点,它也会将其更改为 false。
你可以根据需要定义任意数量的 FocusState变量来覆盖你的焦点管理逻辑。SwiftUI 通过将焦点视图与其绑定保持同步来处理它们。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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("email")) .focused($isEmailFocused) SecureField("password", text: $password, prompt: Text("password")) .focused($isPasswordFocused) } .navigationTitle("Sign in") } } }
|
在上面的例子中,我们有两个变量绑定到电子邮件和密码文本字段。SwiftUI 可以一起管理它们并使它们与用户界面保持同步。请记住,你可以通过编程方式将该值更改为 false 以隐藏键盘或将该值设置为 true 以将焦点移动到特定视图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| 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("email")) .focused($isEmailFocused) SecureField("password", text: $password, prompt: Text("password")) .focused($isPasswordFocused)
Button("login") { if email.isEmpty { isEmailFocused = true } else if password.isEmpty { isPasswordFocused = true } else { isPasswordFocused = false isEmailFocused = false
login() } } } .navigationTitle("Sign in") } }
private func login() { } }
|
多个输入框的焦点判断
在复杂的视图层次结构中定义许多FocusState属性会变得很麻烦。幸运的是,FocusState不仅适用于布尔值,还适用于任何Hashable类型。这意味着我们可以使用符合Hashable协议的枚举类型对聚焦状态进行建模。让我们来看看这个例子。
1 2 3 4
| enum FocusableField: Hashable { case email case password }
|
这里我们有符合Hashable的Field枚举并定义了我们管理的所有可聚焦视图。现在,我们可以使用这个枚举将不同视图的焦点状态绑定到各种枚举案例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| 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() { } }
|
如你所见,我们使用了另一个版本的聚焦视图修饰符来将视图绑定到Field枚举的具体情况。每当用户关注任何绑定视图时,SwiftUI都会更新FocusState属性的值。请记住,我们应该将FocusState属性设为可选,以便与Hashable枚举结合使用,因为目前可能没有聚焦视图。
张洪Heo
分享设计与科技生活
本文是转载或翻译文章,版权归原作者所有。建议访问原文,转载本文请联系原作者。