如何在iOS SwiftUI中检测TextField失去焦点?

34
TextField("Name", text: $name)

我找到了这个方法

func focusable(_ isFocusable: Bool = true, onFocusChange: @escaping (Bool) -> Void = { _ in }) -> some View

但它只适用于MacOS,我该如何在iOS上做类似的事情?

2个回答

54

您可以使用文本字段中存在的初始化程序init(_:text:onEditingChanged:onCommit:)。当您开始编辑和结束编辑时,将会触发一个操作。以下是最简单的示例。

import SwiftUI

struct ContentView: View {
    @State private var greeting: String = "Hello world!"
    var body: some View {
        TextField("Welcome", text: $greeting, onEditingChanged: { (editingChanged) in
            if editingChanged {
                print("TextField focused")
            } else {
                print("TextField focus removed")
            }
        })
    }
}
希望这有所帮助。

Hope this helps.

=>

希望这有所帮助。


这个解决方案的问题在于,如果您没有其他的TextField并且使用.numberPad键盘,则onEditingChanged:将永远不会被调用。onCommit:也不会被调用。 - caram
1
我现在尝试使用.numberPad,看起来它运行良好。我使用的是XCode 11.2 beta版本和iPhone XS Max设备,在iOS 13.2 Developer Beta 4上测试通过。 - Subramanian Mariappan
1
onEditingChanged: 在获取焦点时被调用,而不是在焦点释放时调用(因为如果视图中没有其他 TextField,则没有其他 UI 元素将成为第一响应者)。onCommit: 同样适用。 - caram
2
SwiftUI中的.alert会触发带有false值的onEditingChanged函数。 - Roman Mahotskyi
我在这里评论上面的评论,指出'SwiftUI .alert'会触发'onEditingChanged'函数,并返回false值。我遇到了一个问题。有什么办法让它在用户点击文本框时更改为true吗? - OmegaKi113r
4
这已经被弃用了。 - user626776

53

iOS 15+

在iOS 15中,我们可以使用@FocusState检测变化:

@FocusState private var isFocused: Bool
...

var body: some View {
    Form {
        TextField("Name", text: $name)
            .focused($isFocused)
            .onChange(of: isFocused) { isFocused in
                // ...
            }
    }
}

.onFocus has already been deprecated in favor of @FocusState - harrisg
3
这样为每个文本字段保留一个状态变量以便能够对失去焦点做出反应实在是过度了。很遗憾苹果已将onEditingChanged标记为过时... - G. Marc
如何处理多个字段 - user626776
2
@G.Marc 如果你有多个字段,使用枚举而不是 Bool 没有太大的区别,在 onChange 中检查值是否等于你感兴趣的特定枚举情况即可。 - mota
1
@Fabian,尝试使用枚举代替布尔值来表示焦点状态,这样你就可以绑定更少的焦点状态变量了。 - aehlke
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接