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



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

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

我在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之间切换效果很好,但文本字段不可编辑。

它的行为就像是被禁用了,但事实并非如此。 显式.disabled(false(到文本字段无济于事。 此外,无论如何它都应该已启用,因为 1( 这是默认值,2( 它所在的 VStack 专门设置为启用,以及 3( 确定按钮正常工作。

想法/解决方法?
谢谢!

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

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

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

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

经过一些研究,我通过在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)

最新更新