SwiftUI TextField在ZStack内部的VStack中已被禁用(使用TextField模拟警报)

时间:2019-12-26 21:45:47

标签: swiftui textfield

我需要在 SwiftUI 中创建一个其中包含可编辑的 TextField 的警报。目前,SwiftUI(从 Xcode 11.3 开始)不支持此功能,因此我正在寻找解决方法。

我知道我可以通过将普通的UIKit位包装在 UIHostingController 中来实现,但我真的想坚持使用全Swift的实现。

我在 ZStack 中有两个 VStack ,前一个(带有TextView的)被隐藏并禁用,直到您点击按钮。看看这个:

import SwiftUI

struct ContentView: View {
    @State var isShowingEditField = false
    @State var text: String = "12345"

    var body: some View {
        ZStack {
            VStack {
                Text("Value is \(self.text)")
                Button(action: {
                    print("button")
                    self.isShowingEditField = true
                }) {
                    Text("Tap To Test")
                }
            }
            .disabled(self.isShowingEditField)
            .opacity(self.isShowingEditField ? 0.25 : 1.00)

            VStack(alignment: .center) {
                Text("Edit the text")
                TextField("", text: self.$text)
                    .multilineTextAlignment(.center)
                    .lineLimit(1)

                Divider()
                HStack {
                    Button(action: {
                        withAnimation {
                            self.isShowingEditField = false
                            print("completed... value is \(self.text)")
                        }
                    }) {
                        Text("OK")
                    }
                }
            }
            .padding()
            .background(Color.white)
            .shadow(radius: CGFloat(1.0))
            .disabled(!self.isShowingEditField)
            .opacity(self.isShowingEditField ? 1.0 : 0.0)
        }
    }
}

这似乎应该对我有用。在两个 VStack 之间切换效果很好,但是 TextField 是不可编辑的。

它的行为就像是被禁用,但不是。显式地 .disabled(false)对文本字段没有帮助。另外,它应该已经启用,因为1)是默认设置; 2)专门将其所在的VStack设置为启用; 3)OK按钮正常工作。

想法/解决方法?
谢谢!

3 个答案:

答案 0 :(得分:2)

您需要使用某些方法强制更新TextField。如下所示:

    TextField("", text: self.$text)
                .multilineTextAlignment(.center)
                .lineLimit(1)
                .id(self.isShowingEditField)

答案 1 :(得分:1)

这真的很荒谬,但是如果只注释一行代码,问题就会消失:

//.shadow(radius: CGFloat(1.0))

我评论了,一切正常。我认为您需要在自定义警报视图中的某处使用ZStack来避免这种情况。嗯,可能是错误吗?

更新 尝试一些实验。如果您只在该视图中保留以下代码:

struct CustomAlertWithTextField: View {

    @State var isShowingEditField = false
    @State var text: String = "12345"

    var body: some View {
        TextField("", text: $text)
            .padding()
            .shadow(radius: CGFloat(1.0))
    }
}

它将不再起作用。仅当您评论.padding().shadow(...)

但是,如果您重新启动Xcode-此代码开始起作用(这让我发疯了)。在Xcode版本11.2(11B52)上进行了尝试

更新2 的工作代码版本:

struct CustomAlertWithTextField: View {

    @State var isShowingEditField = false
    @State var text: String = "12345"

    var body: some View {
        ZStack {
            VStack {
                Text("Value is \(self.text)")
                Button(action: {
                    print("button")
                    self.isShowingEditField = true
                }) {
                    Text("Tap To Test")
                }
            }
            .disabled(self.isShowingEditField)
            .opacity(self.isShowingEditField ? 0.25 : 1.00)

            ZStack {
                Rectangle()
                    .fill(Color.white)
                    .frame(width: 300, height: 100)
                    .shadow(radius: 1) // moved shadow here, so it doesn't affect TextField now

                VStack(alignment: .center) {
                    Text("Edit the text")
                    TextField("", text: self.$text)
                        .multilineTextAlignment(.center)
                        .lineLimit(1)
                        .frame(width: 298)

                    Divider().frame(width: 300)

                    HStack {
                        Button(action: {
                            withAnimation {
                                self.isShowingEditField = false
                                print("completed... value is \(self.text)")
                            }
                        }) {
                            Text("OK")
                        }
                    }
                }
            }
            .padding()
            .background(Color.white)
            .disabled(!self.isShowingEditField)
            .opacity(self.isShowingEditField ? 1.0 : 0.0)
        }
    }

}

答案 2 :(得分:1)

经过一些研究,我通过向 VStack 添加 .clipped() 解决了这个问题。

对于您的问题,它看起来像这样:

VStack(alignment: .center) {
    Text("Edit the text")
    TextField("", text: self.$text)
        .multilineTextAlignment(.center)
        .lineLimit(1)

    Divider()
    HStack {
        Button(action: {
            withAnimation {
                self.isShowingEditField = false
                print("completed... value is \(self.text)")
            }
        }) {
            Text("OK")
        }
    }
}
.padding()
.clipped() // <- here
.background(Color.white)
.shadow(radius: CGFloat(1.0))
.disabled(!self.isShowingEditField)
.opacity(self.isShowingEditField ? 1.0 : 0.0)