SwiftUI TextField acts disabled in VStack inside ZStack (simulating an Alert with a TextField)

两盒软妹~` 提交于 2020-05-13 18:47:08

问题


I need to make an Alert in SwiftUI that has an editable TextField in it. Currently, this isn't supported by SwiftUI (as of Xcode 11.3), so I'm looking for a work-around.

I know I can implement by wrapping the normal UIKit bits in a UIHostingController, but really want to stick with an all-SwiftUI implementation.

I've got two VStacks in a ZStack, with the front one (the one with the TextView) being hidden and disabled until until you tap the button. Take a look at this:

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

This seems like it should work to me. Switching between the two VStacks works well, but the TextField is not editable.

It acts like it's disabled, but it's not. Explicitly .disabled(false) to the TextField doesn't help. Also, it should already be enabled anyway since 1) that's the default, 2) the VStack it's in is specifically being set as enabled, and 3) The OK button works normally.

Ideas/workarounds?
Thanks!


回答1:


You need to force the TextField updating with some methods. Like the following:

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



回答2:


That is really ridiculous, but the problem disappears if you comment just one line of code:

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

I commented it and everything works. I think you need to use ZStack somewhere in your custom alert view to avoid this.. hm, bug, maybe?

update try some experiments. If you leave just this code in that View:

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

it would not work again. only if you comment .padding() or .shadow(...)

BUT if you relaunch Xcode - this code begin to work (which made me crazy). Tried it at Xcode Version 11.2 (11B52)

update 2 the working code version:

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

}


来源:https://stackoverflow.com/questions/59493767/swiftui-textfield-acts-disabled-in-vstack-inside-zstack-simulating-an-alert-wit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!