SwiftUI管理视图焦点的focused修饰符
SwiftUI管理视图焦点的focused修饰符

SwiftUI管理视图焦点的focused修饰符

在 SwiftUI 中,focused 修饰符用于管理视图的焦点状态,通常应用于 TextField 和其他支持焦点的输入控件。通过结合 @FocusState 属性包装器,可以灵活地设置和响应焦点的变化。

通常需要使用@FocusState属性包装器:

@FocusState private var isFocused: Bool

在输入控件添加focused修饰符进行管理:

.focused($isFocused)

基本用法

示例代码

import SwiftUI

struct FocusExample: View {
    @FocusState private var isTextFieldFocused: Bool // 焦点状态

    @State private var text: String = ""

    var body: some View {
        VStack {
            TextField("Enter text here", text: $text)
                .focused($isTextFieldFocused) // 绑定焦点状态
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            Button("Toggle Focus") {
                isTextFieldFocused.toggle() // 切换焦点状态
            }
        }
        .padding()
    }
}

#Preview {
    FocusExample()
}

解析

1、@FocusState:用于声明一个焦点状态变量,可以是布尔值,也可以是枚举或其他自定义类型。

2、.focused($isTextFieldFocused):绑定焦点状态到 TextField,当 isTextFieldFocused 为 true 时,该 TextField 会自动获得焦点。

多视图焦点管理

示例代码

import SwiftUI

struct MultiFocusExample: View {
    enum Field: Hashable {
        case firstField
        case secondField
    }

    @FocusState private var focusedField: Field? // 使用枚举管理焦点
    @State private var firstText: String = ""
    @State private var secondText: String = ""

    var body: some View {
        VStack {
            TextField("First Field", text: $firstText)
                .focused($focusedField, equals: .firstField)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            TextField("Second Field", text: $secondText)
                .focused($focusedField, equals: .secondField)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            Button("Focus First Field") {
                focusedField = .firstField
            }

            Button("Focus Second Field") {
                focusedField = .secondField
            }

            Button("Clear Focus") {
                focusedField = nil
            }
        }
        .padding()
    }
}

#Preview {
    MultiFocusExample()
}

解析

1、使用 enum 定义不同焦点的标识符(如 .firstField 和 .secondField)。

2、.focused($focusedField, equals: .firstField):将特定的 TextField 与枚举值绑定。

3、通过切换 focusedField 的值,控制哪一个视图当前获得焦点。

可聚集的键类型

如果列表中每一个字段都含有TextField,在聚焦的过程中需要设置多个或者几十个case。

这种场景不容易维护,根据多视图焦点管理,需要设置很多的case。

enum CurrencyField: Hashable {
    case USD
    case CNY
    case EUR
    ...
}

因此需要通过定义一个可聚焦的键类型:

enum CurrencyField: Hashable {
    case symbol(String)
}

这里的 .symbol(String) 就是一个“可聚焦的键”。这个类型必须遵循 Hashable 协议,SwiftUI 才能识别它。

添加 @FocusState属性:

@FocusState private var focusedField: CurrencyField?

在列表的TextField中使用.focused(…)。

TextField("0.0", text: Binding(get: {
    inputAmounts[currency] ?? ""
}, set: { newValue in
    inputAmounts[currency] = newValue
}))
.focused($focusedField, equals: .symbol(currency)) // 添加这一行

当需要取消聚集时,通过命令将focusedField改为nil即可。

focusedField = nil

这样就会取消聚焦,所有键盘自动关闭。

响应键盘事件

示例代码

import SwiftUI

struct KeyboardExample: View {
    @FocusState private var isFocused: Bool
    @State private var text: String = ""

    var body: some View {
        VStack {
            TextField("Enter text", text: $text)
                .focused($isFocused)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            Button("Dismiss Keyboard") {
                isFocused = false // 移除焦点,隐藏键盘
            }
        }
        .padding()
    }
}

#Preview {
    KeyboardExample()
}

解析

1、isFocused = false:移除焦点,键盘会自动隐藏。

2、在实际应用中,这种方法通常与手势(如 onTapGesture)配合使用。

使用场景

1、控制键盘显示与隐藏:当视图需要主动控制键盘时,可以通过焦点管理实现。

2、多输入框切换焦点:在多个 TextField 之间切换时,使用枚举或标志位。

3、响应外部事件:如点击按钮或手势时移除焦点。

注意事项

1、@FocusState 只适用于 iOS 15 及以上版本。

2、focused 修饰符需要和支持焦点的视图配合使用(如 TextField 或 SecureField)。

3、如果焦点状态过于复杂,可以考虑封装到自定义视图中以简化代码。

相关文章

SwiftUI隐藏键盘:https://fangjunyu.com/2024/09/23/swiftui%e9%9a%90%e8%97%8f%e9%94%ae%e7%9b%98/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注