【问题标题】:How to Hide Keyboard in SwiftUI Form Containing Picker?如何在包含选取器的 SwiftUI 表单中隐藏键盘?
【发布时间】:2019-10-22 20:13:57
【问题描述】:

我有一个SwiftUIForm,其中包含一个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:

我可以很方便的选择picker中的第二个item,如下图:

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

为了在更新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 的不同部分会关闭键盘:

到目前为止,一切都按预期进行。但是,我想在点击TextField 之外的任何位置时关闭键盘,因为我无法弄清楚在拖动 Form 包含滚动视图时如何关闭键盘。

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

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

以下两个截图显示TextField能够成为第一响应者并显示键盘。然后在TextField之外点击时成功关闭键盘:

但是,当尝试选择 `Picker.事实上,即使在键盘被关闭后,我也无法选择不同的段。我认为无法选择不同的段,因为附加到表单的点击手势阻止了选择。

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

我可以做些什么来允许选择Picker 的段,同时允许在TextField 之外点击时关闭键盘?

【问题讨论】:

    标签: swiftui swiftui-form


    【解决方案1】:
    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 时才启用表单的点击手势(通过点击任意位置完成编辑)

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

    【讨论】:

      【解决方案2】:

      您可以将所有代码放在 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 的背景颜色更改为红色可以简化确定用户可能单击以关闭的位置。

      复制并粘贴代码以获得准备运行的示例。

      【讨论】:

      • 很遗憾,这个解法的结果和我的解法结果一样。
      • 这是因为您的 .onTapGesture 已附加到 Form{ code }。尝试使用带有 Spacers() 的 VStack{} 和 HStack{} 来“为 HStack { TextField() Text() } 着色并为红色下方的空白区域着色”。目前您的整个视图都是“红色”的。
      猜你喜欢
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 2020-09-11
      • 2022-09-29
      • 1970-01-01
      • 2016-07-16
      • 1970-01-01
      • 2021-09-16
      相关资源
      最近更新 更多