如何在包含Picker的SwiftUI表单中隐藏键盘?

时间:2019-10-22 20:13:57

标签: swiftui swiftui-form

我有一个SwiftUI Form,其中包含一个Picker,一个TextField和一个Text

struct ContentView: View {

    var body: some View {
        Form {
            Section {
                Picker(selection: $selection, label: label) {
                    // Code to populate picker
                }.pickerStyle(SegmentedPickerStyle())
                HStack {
                    TextField(title, text: $text)
                    Text(text)
                }
            }
        }
    }

}

上面的代码将产生以下UI:

Screenshot of iOS application that displays a picker and a text field with a label

我能够在选择器中轻松选择第二项,如下所示:

Screenshot of iOS application that displays an updated selection in the picker

下面,您可以看到我可以通过点击TextField来启动文本输入:

Screenshot of iOS application that displays keyboard for text entry in text field

为了在更新Picker值时关闭键盘,添加了Binding,可以在以下代码块中看到它:

Picker(selection: Binding(get: {
        // Code to get selected segment
    }, set: { (index) in
        // Code to set selected segment
        self.endEditing()
    }), label: label) {
        // Code to populate picker
    }

通过以下方法提供了对self.endEditing()的调用:

func endEditing() {
    sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}

以下屏幕截图显示,选择Picker的其他部分会关闭键盘:

Screenshot of iOS application that displays dismissed keyboard when selecting new segment of picker

到目前为止,一切正常。但是,我想在点击TextField之外的任何地方时关闭键盘,因为我无法弄清楚在拖动Form的包含滚动视图时如何关闭键盘。

我尝试添加以下实现以在点击Form时关闭键盘:

Form {
    Section {
        // Picker
        HStack {
            // TextField
            // Text
        }
    }
}.onTapGesture {
    self.endEditing()
}

下面的两个截屏显示TextField能够成为第一响应者并显示键盘。然后,在TextField外部点击时,键盘成功关闭:

Screenshot of iOS application that displays displayed keyboard after tapping text field

但是,尝试选择`Picker的其他部分时,键盘不会关闭。实际上,即使关闭了键盘,我也无法选择其他段。我认为无法选择其他段,因为附加到表单的轻击手势会阻止选择。

以下屏幕截图显示了在显示键盘并实现轻击手势的情况下尝试在Picker中选择第二个值的结果:

Screenshot of iOS application that displays displayed keyboard and previously-selected picker segment

我该怎么做才能选择Picker的段,同时在TextField之外点击时允许关闭键盘?

2 个答案:

答案 0 :(得分:0)

您可以将所有代码放置在VStack {code}中,向其添加一个Spacer()并将onTap添加到此VStack。这将允许您通过单击屏幕上的任意位置来关闭键盘。

请参见下面的代码:

import SwiftUI

struct ContentView: View {

        @State private var text: String = "Test"

        var body: some View {
            VStack {
                HStack {
                    TextField("Hello World", text: $text)
                    Spacer()
                }
                Spacer()
            }
            .background(Color.red)
            .onTapGesture {
                self.endEditing()
            }
        }

        func endEditing() {
            UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
        }
    }

将HStack或VStack的背景颜色更改为红色可简化找出用户单击以消除的位置。

复制并粘贴代码以准备运行。

答案 1 :(得分:0)

import SwiftUI

struct ContentView: View {
    @State private var tipPercentage = 2
    let tipPercentages = [10, 15, 20, 25, 0]
    @State var text = ""

    @State var isEdited = false
    var body: some View {
        Form {
            Section {
                Picker("Tip percentage", selection: $tipPercentage) {
                    ForEach(0 ..< tipPercentages.count) {
                        Text("\(self.tipPercentages[$0])%")
                    }
                }
                .pickerStyle(SegmentedPickerStyle())
                HStack {
                    TextField("Amount", text: $text, onEditingChanged: { isEdited in
                        self.isEdited = isEdited
                    }).keyboardType(.numberPad)
                }
            }
        }.gesture(TapGesture().onEnded({
            UIApplication.shared.windows.first{$0.isKeyWindow }?.endEditing(true)
        }), including: isEdited ? .all : .none)
    }

}

仅当文本字段isEdited == true

时,启用Form的点击手势(通过在任意位置完成点击编辑)

一旦isEdited == false,您的选择器就会像以前一样工作。