3

可能没有办法使用自定义来测量触摸压力UIGestureRecognizer,因为我们不能直接访问系统键盘的视图 [1]。如果使用自定义可以实现,inputViewController但它不是我的选择。我想存储每个键的按键保持时间和按键压力。你知道这样做的方法吗?

编辑:[1] 我说“我们不能直接访问系统键盘的视图。” 但实际上我们可以: UIRemoteKeyboardWindow > InputSetContainerView > InputSetHostView

我认为对 Nirav Bhatt 答案的改进可能会解决这个问题,但它会禁用键盘视图上的触摸功能。当我触摸一个键时,它会输出触摸力,但相应的字母不会输入到文本字段中。

4

2 回答 2

3

从 iOS 9 开始,作为 3D touch 的一部分,UITouch 具有 force 属性,可以准确地获取在触摸事件期间施加的压力。

您可以将此与您的自定义视图实现结合起来,将每个字母数字字符作为 UIButtons 接收触摸并将其传递。

更新:

经过一番讨价还价后UIWindow,我终于能够在苹果的标准键盘窗口中捕获触摸事件。

hittest诀窍是在扩展中覆盖UIWindow(也可以在UIView级别上完成,但它会产生更广泛的影响,因为UIView它是 的祖先UIWindow),并在您看到来自 的触摸时返回触摸处理对象UIRemoteKeyboardWindow

extension UIWindow
{
    override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    {
        print("kb touch")

        for touch in touches
        {
           let pressure = touch.force
           print("pressure is: \(String(describing: pressure))")
        }
    }

    override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        print("hittest")

        let view = super.hitTest(point, with: event)

        if (NSStringFromClass(type(of: self)) == "UIRemoteKeyboardWindow")
        {
            //will result in touchesBegan being called
            return self;
        }

        return view
    }
}
于 2018-08-08T08:03:26.540 回答
0

解决方案比我想象的要容易。对于 iOS 9+ 系统,我们可以按照以下步骤访问系统键盘并监听按键...

首先,创建一个自定义UIGestureRecognizer来监听击键。跳过此步骤的实现,因为它很简单(只需覆盖touchesBegan, touchesMoved, touchesEnded)。

添加KeyboardManager以访问键盘视图:

final class KeyboardManager {

    static let shared = KeyboardManager()

    private init() { }

    /// Returns keyboard view on application window
    ///
    /// - Returns: Keyboard view
    func keyboardView() -> UIView? {
        for window in UIApplication.shared.windows {
            if let keyboardView = keyboardViewFromWindow(window) {
                return keyboardView
            }
        }
        return nil
    }

    /// Returns keyboard view from given window
    ///
    /// - Parameter window: Keyboard view container candidate window
    /// - Returns: Keyboard view
    func keyboardViewFromWindow(_ window: UIWindow) -> UIView? {
        if window.hasClassNameSuffix("UIRemoteKeyboardWindow") {
            let inputSetContainerView = window.subview(withSuffix: "InputSetContainerView")
            let inputSetHostView = inputSetContainerView?.subview(withSuffix: "InputSetHostView")
            return inputSetHostView
        }

        return nil
    }
}

UIView上面使用的扩展函数:

@nonobjc extension UIView {

    /// Returns first found subview with given class name
    ///
    /// - Parameter className: Subview class name
    /// - Returns: First subview with given class name
    func subview(withSuffix className: String) -> UIView? {
        return subviews.first {
            $0.hasClassNameSuffix(className)
        }
    }

    /// Compares suffix of view class name with given name
    ///
    /// - Parameter className: Class name that will be compared
    /// - Returns: Comparison result of view class name and given name
    func hasClassNameSuffix(_ className: String) -> Bool {
        return NSStringFromClass(type(of: self)).hasSuffix(className)
    }
}

然后,使用以下函数将手势识别器添加到键盘视图:

KeyboardManager.shared.keyboardView()?.addGestureRecognizer(keyboardGestureRecognizer).

注意:您的手势识别器不应扩展UITapGestureRecognizer. UILongPressGestureRecognizer没关系。我们不能将多个具有相同类型的点击手势识别器添加到视图中。

于 2018-08-21T09:08:05.177 回答