How to add a TextField to Alert in SwiftUI?

前端 未结 9 1936
温柔的废话
温柔的废话 2021-02-03 21:33

Anyone an idea how to create an Alert in SwiftUI that contains a TextField?

\"sample_image\"

9条回答
  •  独厮守ぢ
    2021-02-03 22:12

    I found modals and alerts in SwiftUI to be lacking several features. For instance, there doesn't seem to be a way of presenting a modal with FormSheet style.

    When I need to present a complex alert (such as one with textfields), I create a pure SwiftUI view with all the content of the alert, and then present it as a FormSheet using a UIHostController.

    If you do not have a UIViewController around to call present(), you can always use the root view controller.

    With this approach you get some nice features, such as the standard alert animation both going in, and out. You can also drag the alert down to dismiss it.

    The alert view also moves up when the keyboard appears.

    This works nicely on iPad. On iPhone, FormSheet is full screen so you may need to tweak the code to find a solution. I think this will give you a good starting point.

    It is something like this:

    struct ContentView : View {
        @State private var showAlert = false
    
        var body: some View {
            VStack {
                Button(action: {
                    let alertHC = UIHostingController(rootView: MyAlert())
    
                    alertHC.preferredContentSize = CGSize(width: 300, height: 200)
                    alertHC.modalPresentationStyle = UIModalPresentationStyle.formSheet
    
                    UIApplication.shared.windows[0].rootViewController?.present(alertHC, animated: true)
    
                }) {
                    Text("Show Alert")
                }
            }
        }
    }
    
    struct MyAlert: View {
        @State private var text: String = ""
    
        var body: some View {
    
            VStack {
                Text("Enter Input").font(.headline).padding()
    
                TextField($text, placeholder: Text("Type text here")).textFieldStyle(.roundedBorder).padding()
                Divider()
                HStack {
                    Spacer()
                    Button(action: {
                        UIApplication.shared.windows[0].rootViewController?.dismiss(animated: true, completion: {})
                    }) {
    
                        Text("Done")
                    }
                    Spacer()
    
                    Divider()
    
                    Spacer()
                    Button(action: {
                        UIApplication.shared.windows[0].rootViewController?.dismiss(animated: true, completion: {})
                    }) {
                        Text("Cancel")
                    }
                    Spacer()
                }.padding(0)
    
    
                }.background(Color(white: 0.9))
        }
    }
    

    If you find yourself using this a lot, the button row may be encapsulated in a separate view for easy reuse.

提交回复
热议问题