【问题标题】:How to remap a touch to another window?如何将触摸重新映射到另一个窗口?
【发布时间】:2020-02-14 08:05:26
【问题描述】:

我有一台带外接触摸屏的 iPad。我正在尝试将外部触摸屏的坐标系重新映射到那里显示的UIWindow

我正在触摸 iPad 上显示的 UIWindowUIViewController,就好像我在触摸 iPad。我确实使用触摸类型.stylus 来获取它们,这就是我如何将它们与实际的 iPad 触摸区分开来(我将在 iPad 和外部屏幕上显示不同的视图)。我正在使用以下代码:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touchesOnExternalWindow = touches.filter({ $0.type == .stylus })
    let touchesOnIpad = touches.subtracting(touchesOnExternalWindow)
    if !touchesOnIpad.isEmpty {
        super.touchesBegan(touchesOnIpad, with: event)
    }

    if !touchesOnExternalWindow.isEmpty {
        guard let externalWindow = UIApplication.shared.windows.first(where: { $0.screen.bounds == screenBounds }) else {
            fatalError("Touching the external display without an external display is not supported!")
        }

        externalWindow.rootViewController?.view.touchesBegan(touchesOnExternalWindow, with: event)
    }
}

我试图将触摸传递给第二个UIWindow,就好像我在触摸那里一样。但这似乎不起作用。

如何以编程方式触摸视图?我现在正在使用第二个屏幕上的按钮进行测试,但它也需要与 SceneKit 视图一起使用。

【问题讨论】:

    标签: ios uiresponder


    【解决方案1】:

    您一次只能有一个第一响应者,它只能将事件传递给一个下一个响应者。 因此,如果您想在外部窗口中使用触控笔处理触摸,则需要将此代码放入您的 iPad UIViewController 下一个响应者中(不清楚 iPad UIViewController 的下一个响应者是谁)。 在 iPad UIViewController 的下一个响应者中,放置以下代码:

    override var next: UIResponder? {
        // The next responder of The UIResponder chain.
        // It will receive responder events (like touches)
        // that current responder (your iPad window UIViewController next reponder) did't handle.
        guard let externalWindow = UIApplication.shared.windows.first(where: { $0.screen.bounds == screenBounds }) else { 
           fatalError("Touching the external display without an external display is not supported!")
         }
        return externalWindow
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touchesOnExternalWindow = touches.filter({ $0.type == .stylus })
        let touchesOnIpad = touches.subtracting(touchesOnExternalWindow)
        if !touchesOnIpad.isEmpty {
            // Here you handle your touches on iPad, instead of passing it to next responder
        }
    
        // Pass touches to next responder(external window).
        if !touchesOnExternalWindow.isEmpty {
            super.touchesBegan(touchesOnExternalWindow, with: event)
        }
    }
    

    【讨论】:

    • 你在一个不返回任何东西的方法中返回nil
    • @vrwim 我为错误道歉。我们需要前向调用 super,而不是返回 nil。我编辑了我的答案。
    • @vrwim 我正在添加最终版本。据我了解,您想要处理除手写笔触摸事件之外的所有事件(正如您所说的要在 iPad 上绘制一些视图),并将手写笔触摸传递给外部窗口。问题是您不能将事件传递给多个下一个响应者。如果你不想处理这种触摸,你需要在你当前的响应者 tochesBegan 方法中处理它(或者你可能不想以某种方式将它传递给另一个对象),并且在你完成后将样式触摸事件传递给你的外部窗口。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多