[英]TextField with animation crashes app and looses focus
Minimal reproducible example:最小可重现示例:
In SceneDelegate.swift
:在
SceneDelegate.swift
:
let contentView = Container()
In ContentView.swift
:在
ContentView.swift
:
struct SwiftUIView: View {
@State var text: String = ""
var body: some View {
VStack {
CustomTextFieldView(text: $text)
}
}
}
struct Container: View {
@State var bool: Bool = false
@State var text: String = ""
var body: some View {
Button(action: {
self.bool.toggle()
}) {
Text("Sheet!")
}
.sheet(isPresented: $bool) {
SwiftUIView()
}
}
}
In CustomTextField.swift
:在
CustomTextField.swift
中:
struct CustomTextFieldView: View {
@Binding var text: String
@State var editing: Bool = false
var body: some View {
Group {
if self.editing {
textField
.background(Color.red)
} else {
ZStack(alignment: .leading) {
textField
.background(Color.green)
Text("Placeholder")
}
}
}
.onTapGesture {
withAnimation {
self.editing = true
}
}
}
var textField: some View {
TextField("", text: $text)
}
Problem:问题:
After running the above code and focusing the text field, the app crashes.运行上述代码并聚焦文本字段后,应用程序崩溃了。 Some things I noticed:
我注意到的一些事情:
withAnimation
code, or the ZStack
in CustomTextField
file, the app doesn't crash, but the TextField looses focus.withAnimation
代码或CustomTextField
文件中的ZStack
,应用程序不会崩溃,但 TextField 会失去焦点。VStack
in SwiftUIView
, the app doesn't crash, but the TextField looses focus.VStack
中的SwiftUIView
,应用程序不会崩溃,但 TextField 会失去焦点。 Questions:问题:
You have two of them.你有两个。 Two different TextField could not be in editing state at the same time.
两个不同的TextField不能同时在编辑state。
The approach suggested by Asperi is the only possible. Asperi 建议的方法是唯一可行的方法。
The reason, why your code crash is not easy explain, but expected in current SwiftUI.你的代码崩溃的原因不容易解释,但在当前 SwiftUI 中是预期的。
You have to understand, that Group is not a standard container, it just like a "block" on which you can apply some modifiers.您必须了解,Group 不是标准容器,它就像一个“块”,您可以在其上应用一些修饰符。 Removing Group and using wraping body in ViewBuilder
删除组并在 ViewBuilder 中使用包装体
struct CustomTextFieldView: View {
@Binding var text: String
@State var editing: Bool = false
@ViewBuilder
var body: some View {
if self.editing {
TextField("", text: $text)
.background(Color.red)
.onTapGesture {
self.editing.toggle()
}
} else {
ZStack(alignment: .leading) {
TextField("", text: $text)
.background(Color.green)
.onTapGesture {
self.editing.toggle()
}
}
}
}
}
the code will stop to crash, but there is other issue, the keyboard will dismiss immediately.代码将停止崩溃,但还有其他问题,键盘将立即关闭。 That is due the tap gesture applied.
这是由于应用了点击手势。
So, believe or not, you have to use ONE TextField ONLY.所以,不管你信不信,你必须只使用一个 TextField。
struct CustomTextFieldView: View {
@Binding var text: String
@State var editing = false
var textField: some View {
TextField("", text: $text, onEditingChanged: { edit in
self.editing = edit
})
}
var body: some View {
textField.background(editing ? Color.green : Color.red)
}
}
Use this custom text field elsewhere in your code, as you want根据需要在代码的其他位置使用此自定义文本字段
Try the following for CustomTextFieldView
(tested & works with Xcode 11.2 / iOS 13.2)为
CustomTextFieldView
尝试以下操作(已测试并适用于 Xcode 11.2 / iOS 13.2)
struct CustomTextFieldView: View {
@Binding var text: String
@State var editing: Bool = false
var body: some View {
TextField("", text: $text)
.background(self.editing ? Color.red : Color.green)
.onTapGesture {
withAnimation {
self.editing = true
}
}
}
}
How can I keep the focus of the TextField after the body is recalculated because of a change in state?
由于 state 的变化,在重新计算正文后,如何保持 TextField 的焦点?
You don't loose focus, you just remove entire text field, so the solution is not replace text field, but modify its property, ie background.你没有失去焦点,你只是删除了整个文本字段,所以解决方案不是替换文本字段,而是修改它的属性,即背景。 It's ok to put it into ZStack, but keep it one.
放到ZStack里没问题,但还是留着吧。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.