【问题标题】:Detect and forward taps anywhere on screen in SwiftUI在 SwiftUI 中检测和转发屏幕上任意位置的点击
【发布时间】:2020-10-05 14:35:18
【问题描述】:

在 SwiftUI 应用程序中,我需要检测屏幕上的任何点击。仅检测,然后将其转发到底层视图。作为一个用例,考虑向服务器发送“在线”用户状态更新以响应任何用户活动。

我当然不想为此目的在每个视图中添加手势识别器。我尝试在 SceneDelegate 中添加一个全局的。就检测到任何水龙头而言,这都是有效的:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {        
    // ... snip other code
    initGlobalTapRecognizer()
}

// MARK: UIGestureRecognizerDelegate
extension SceneDelegate: UIGestureRecognizerDelegate {
    func initGlobalTapRecognizer() {
        let tapGesture = UITapGestureRecognizer(target: self, action: nil)
        tapGesture.delegate = self
        window?.addGestureRecognizer(tapGesture)
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        print("tapped")
        return true
    }
}

但这会破坏一些 SwiftUI 控件。例如,按钮可以工作,但 TabView 不再响应点击。

我尝试了另一种方式,将simultaneousGesture 用作suggest here

struct ContentView: View {
    @State var selectedTab: Int = 1

    var body: some View {
        TabView(selection: $selectedTab) {
            VStack {
                Text("tab 1")
                Button(action: { print("button 1 click") }, label: { Text("button 1") })
            }
            .tabItem( { Text("tab 1") } )
            .tag(1)

            VStack {
                Text("tab 2")
            }
            .tabItem( { Text("tab 2") } )
            .tag(2)
        }
        .contentShape(Rectangle())
        .simultaneousGesture(TapGesture().onEnded({ print("simultaneous gesture tap") }))
    }
}

同样的结果,按钮工作,但 TabView 坏了。

任何想法如何让它工作?

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    作为一个用例,考虑向服务器发送“在线”用户状态更新以响应任何用户活动。

    1. 为全局手势识别器创建扩展:
    extension UIApplication {
        func addGestureRecognizer() {
            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 {
            print("touch detected")
            return true
        }
    
        public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true
        }
    }
    
    1. 将其添加到根窗口:

    SwiftUI 1 版本:

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {        
        // ...
        addGestureRecognizer()
    }
    

    SwiftUI 2 版本:

    @main
    struct TestApp: App {
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .onAppear(perform: UIApplication.shared.addGestureRecognizer)
            }
        }
    }
    
    1. 现在手势识别器已附加到根窗口,并将与其他控件同时被识别:
    struct ContentView: View {
        var body: some View {
            TabView {
                Button("Tap me") {
                    print("Button tapped")
                }
                .tabItem {
                    Text("One")
                }
                List {
                    Text("Hello")
                    Text("World")
                }
                .tabItem {
                    Text("Two")
                }
            }
        }
    }
    

    或者,您可以按照建议的here 创建自定义AnyGestureRecongizer 来检测任何手势。

    【讨论】:

    • 太棒了,非常感谢。专门针对问题中描述的某些 SwiftUI 控件遇到了这个问题。
    【解决方案2】:

    你有没有尝试设置

     cancelsTouchesInView = false 
    

    在你的 TapGesture 中?

    【讨论】:

      猜你喜欢
      • 2014-10-19
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多