带有动画的TextField使应用程序崩溃并失去焦点

时间:2020-02-23 19:32:46

标签: swift swiftui

最小可复制示例:

SceneDelegate.swift中:

let contentView = Container()

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()
        }
    }
}

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)
    }

问题:

运行上面的代码并突出显示文本字段后,应用程序崩溃。我注意到了一些事情:

  1. 如果我删除了withAnimation代码或ZStack文件中的CustomTextField,则该应用不会崩溃,但是TextField失去了焦点。
  2. 如果我删除VStack中的SwiftUIView,则应用不会崩溃,但TextField会失去焦点。
  3. 如果我使用NavigationLink或显示不带图纸的TextField,则应用程序不会崩溃,但TextField会失去焦点。

问题:

  • 在当前版本的SwiftUI中这是问题吗?
  • 使用SwiftUI是否可以解决此问题?我想远离 尽可能使用ViewRepresentables。
  • 由于状态变化重新计算正文后,如何保持TextField的焦点?

2 个答案:

答案 0 :(得分:1)

  1. 在正文之后,如何保持TextField的焦点 是否因为状态变化而重新计算?

您有两个。 两个不同的TextField不能同时处于编辑状态。

唯一可行的方法是Asperi建议。

代码崩溃的原因并不容易解释,但是在当前的SwiftUI中是可以预期的。

您必须了解,组不是标准容器,就像一个“块”,您可以在其上应用一些修饰符。在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()
                        }
                }
        }

    }
}

代码将停止崩溃,但是还有其他问题,键盘将立即关闭。那是由于应用了点击手势。

所以,信不信由你,您只能使用一个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)

    }
}

根据需要在代码的其他位置使用此自定义文本字段

答案 1 :(得分:0)

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
                }
            }
    }
}

由于状态变化重新计算正文后,如何保持TextField的焦点?

您不会失去焦点,只需删除整个文本字段即可,因此解决方案不是替换文本字段,而是修改其属性(即背景)。可以将其放入ZStack中,但请保留其中一个。