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

dre*_*ter 5 textfield swiftui

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

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

我在ZStack 中有两个VStacks,前面的一个(带有 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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

它就像被禁用一样,但事实并非如此。对 TextField显式.disabled(false)没有帮助。此外,无论如何它都应该已经启用,因为 1) 这是默认设置,2) 它所在的 VStack 被专门设置为启用,以及 3) OK 按钮正常工作。

想法/解决方法?
谢谢!

E.C*_*oms 7

您需要使用某些方法强制更新 TextField。像下面这样:

    TextField("", text: self.$text)
                .multilineTextAlignment(.center)
                .lineLimit(1)
                .id(self.isShowingEditField)
Run Code Online (Sandbox Code Playgroud)

  • 电子商务——但这没有意义。默认是启用的,你可以显式地在上面加上 .disable(false) ,这没有什么区别。但这一定是一个错误,对吧? (2认同)

Але*_*кий 6

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

//.shadow(radius: CGFloat(1.0))
Run Code Online (Sandbox Code Playgroud)

我评论了它,一切正常。我认为您需要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))
    }
}
Run Code Online (Sandbox Code Playgroud)

它不会再工作了。仅当您发表评论.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)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)