FocusState属性包装器的基本用法

152 阅读1分钟

在 SwiftUI 中,@FocusState 是一个属性包装器,用于管理和跟踪视图中的焦点状态,通常用于控制 TextFieldTextEditor 或按钮等可聚焦组件的键盘焦点。它可以帮助你实现以下功能:

  • 控制键盘的弹出和收起
  • 在多个输入框之间切换焦点(例如登录表单的“下一步”跳转)
  • 结合 onSubmit 实现表单提交逻辑

基本用法

1. 控制单个 TextField 的焦点

import SwiftUI

struct ContentView: View {
    @State private var text: String = ""
    @FocusState private var isFocused: Bool  // 表示是否获得焦点

    var body: some View {
        VStack {
            TextField("请输入内容", text: $text)
                .focused($isFocused)  // 绑定焦点状态
                .textFieldStyle(.roundedBorder)
                .padding()

            Button("切换焦点") {
                isFocused.toggle()  // 手动控制焦点
            }
        }
        .padding()
    }
}
  • @FocusState 定义了一个布尔值 isFocused,表示 TextField 是否获得焦点。
  • .focused($isFocused) 绑定焦点状态。
  • 点击按钮可以切换 TextField 的焦点状态(键盘弹出/收起)。

2. 多个 TextField 之间切换焦点

struct ContentView: View {
    @State private var username: String = ""
    @State private var password: String = ""
    
    // 定义焦点状态,使用枚举管理不同输入框
    enum FocusField: Hashable {
        case username, password
    }
    @FocusState private var focusedField: FocusField?

    var body: some View {
        VStack {
            TextField("用户名", text: $username)
                .focused($focusedField, equals: .username)
                .textFieldStyle(.roundedBorder)
                .submitLabel(.next)  // 键盘右下角显示“下一步”
                .onSubmit {
                    focusedField = .password  // 按下“下一步”跳转到密码输入框
                }

            TextField("密码", text: $password)
                .focused($focusedField, equals: .password)
                .textFieldStyle(.roundedBorder)
                .submitLabel(.done)  // 键盘右下角显示“完成”
                .onSubmit {
                    focusedField = nil  // 收起键盘
                }

            Button("登录") {
                if username.isEmpty {
                    focusedField = .username
                } else if password.isEmpty {
                    focusedField = .password
                } else {
                    focusedField = nil  // 收起键盘
                    // 处理登录逻辑...
                }
            }
        }
        .padding()
        .onAppear {
            // 页面加载时自动聚焦用户名输入框
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                focusedField = .username
            }
        }
    }
}
  • 使用 enum 管理多个输入框的焦点,避免硬编码。
  • .submitLabel(.next) 修改键盘右下角按钮为“下一步”,方便用户跳转。
  • .onSubmit 监听键盘的“提交”操作,自动切换焦点或提交表单。

进阶用法

1. 结合 onAppear 自动聚焦

.onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        focusedField = .username
    }
}
  • 页面加载后自动聚焦第一个输入框(DispatchQueue 延迟确保动画流畅)。

2. 检测键盘是否弹出

@FocusState private var isKeyboardVisible: Bool
  • 可以用 isKeyboardVisible 判断键盘是否弹出,并调整布局(例如上移输入框避免遮挡)。

3. 结合 ScrollView 优化输入体验

ScrollView {
    VStack {
        // 多个输入框...
    }
}
  • 当键盘弹出时,ScrollView 可以滚动,确保输入框可见。

总结

场景代码示例
单个输入框焦点控制@FocusState var isFocused + .focused($isFocused)
多个输入框切换enum FocusField + @FocusState var focusedField
键盘“下一步”跳转.submitLabel(.next) + .onSubmit
自动聚焦.onAppear { focusedField = .username }
手动收起键盘focusedField = nil

@FocusState 是 SwiftUI 中管理键盘焦点的推荐方式,比传统的 UIResponderbecomeFirstResponder)更简洁高效。适用于表单、搜索框、登录页等场景。