繁体   English   中英

SwiftUI 键盘关闭问题

[英]SwiftUI Keyboard Dismissing Issues

目标是能够在点击屏幕上的任意位置时关闭键盘。 我现在尝试了两种方法,每种方法都提出了不同的问题。

方法一

拿一个给定的屏幕,然后用点击手势包裹它:

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

在最后的黑客攻击中,我确实尝试了以下操作。 有点管用。 它只是不像一个适当的分段控件:

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 的问题,然后我选择了选项二并将 UIKit 轻击手势应用于 window,如下所示:

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

问题:使用这种方法,分段控制有效。 但是,如果您从一个文本字段点击到另一个文本字段,您会发现键盘会上下弹跳。 这是因为 window 手势检测到点击并试图关闭键盘,然后另一个文本字段注册为第一响应者,然后打开键盘并因此弹跳。

唉,这种弹跳是不希望的。 使用方法一,这不会发生。 我有点进退两难。 任何人都知道如何让分段控件以方法 1 响应或在方法 2 中停止弹跳键盘?

我个人认为方法一应该可行,并且分段控件有一个错误,应该报告给 Apple。

只需将点击手势应用于背景即可。 现在您可以通过点击蓝色背景来关闭任何内容:

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(maxWidth: .infinity, maxHeight: .infinity)
        .background(
            Color.blue
                .opacity(0.4)
                .onTapGesture {
                    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                }
        )
    }
}

结果:

结果

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM