我需要在 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按钮正常工作。
想法/解决方法?
谢谢!
答案 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)