【发布时间】:2021-10-04 10:10:16
【问题描述】:
目标是能够在点击屏幕上的任意位置时关闭键盘。我现在尝试了两种方法,每种方法都有不同的问题。
方法一
选取一个给定的屏幕,然后用一个点击手势将其包裹起来:
struct ContentView: View {
@State private var favoriteColor = 0
@State private var text1:String = ""
@State private var text2:String = ""
var body: some View {
VStack {
TextField("Type Things", text: $text1)
TextField("Type More Things", text: $text2)
Picker("What is your favorite color?", selection: $favoriteColor) {
Text("Red").tag(0)
Text("Green").tag(1)
}
.pickerStyle(.segmented)
}
.frame(
minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .center
)
.background(Color.blue.opacity(0.4))
.onTapGesture {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
}
问题:
轻击手势适用于除分段控制之外的所有控件。当您按下给定的分段选项时,分段轻击手势似乎不会将控件移动到所选选项。在我看来,这似乎是一个 SwiftUI 错误。我尝试了.simultaneousGesture(TapGesture().onEnded { })的各种排列方式
Picker("What is your favorite color?", selection: $favoriteColor) {
Text("Red").tag(0)
Text("Green").tag(1)
}
.pickerStyle(.segmented)
.simultaneousGesture(TapGesture().onEnded { })
和.highPriorityGesture(TapGesture().onEnded { })
Picker("What is your favorite color?", selection: $favoriteColor) {
Text("Red").tag(0)
Text("Green").tag(1)
}
.pickerStyle(.segmented)
.highPriorityGesture(TapGesture().onEnded { })
在最后的 hack 中,我确实尝试了以下操作。它有点工作。它只是不像一个适当的分段控件:
Picker("What is your favorite color?", selection: $favoriteColor) {
Text("Red").tag(0)
Text("Green").tag(1)
}
.pickerStyle(.segmented)
.onTapGesture {
if self.favoriteColor == 0 {
self.favoriteColor = 1
} else {
self.favoriteColor = 0
}
}
接近二
鉴于 seg 的问题,然后我选择了选项 2 并将 UIKit 轻击手势应用于窗口,如下所示:
struct ContentView: View {
@State private var favoriteColor = 0
@State private var text1:String = ""
@State private var text2:String = ""
var body: some View {
VStack {
TextField("Type Things", text: $text1)
TextField("Type More Things", text: $text2)
Picker("What is your favorite color?", selection: $favoriteColor) {
Text("Red").tag(0)
Text("Green").tag(1)
}
.pickerStyle(.segmented)
}
.frame(
minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .center
)
.background(Color.blue.opacity(0.4))
}
}
extension UIApplication {
func dismissKeyboardGestureRecognizer() {
guard let window = windows.first else { return }
let gesture = UITapGestureRecognizer(target: window, action: nil)
gesture.requiresExclusiveTouchType = false
gesture.cancelsTouchesInView = false
gesture.delegate = self
window.addGestureRecognizer(gesture)
}
}
extension UIApplication: UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
return true
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
@main
struct SeggyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
UIApplication.shared.dismissKeyboardGestureRecognizer()
}
}
}
}
问题: 使用这种方法,分段控制起作用。但是,如果您从一个文本字段点击到另一个,您会发现键盘上下弹跳。这是因为窗口手势检测到点击并尝试关闭键盘,然后其他文本字段注册为第一响应者,然后将键盘抬起并因此弹跳。
唉,这种弹跳是不需要的。使用方法一,这不会发生。我有点卡在岩石和坚硬的地方之间。任何人都知道如何让分段控件响应方法 1 或停止方法 2 中的弹跳键盘?
我个人认为方法一应该可行,分段控件有错误,应该报告给 Apple。
【问题讨论】:
-
我建议将点击手势放在背景视图而不是全部视图上