代码之家  ›  专栏  ›  技术社区  ›  Dorukhan Arslan

如何测量iOS系统键盘上的触摸压力(击键)?

  •  3
  • Dorukhan Arslan  · 技术社区  · 6 年前

    可能没有办法用自定义的 UIGestureRecognizer ,因为我们无法直接访问系统键盘的视图[1]。如果一个习惯 inputViewController 是用过的,但对我来说不是一个选择。我想为每把钥匙储存钥匙保持时间和按键压力。你知道怎么做吗?

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

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

    2 回复  |  直到 6 年前
        1
  •  3
  •   Nirav Bhatt    6 年前

    从iOS 9开始,作为3D触摸的一部分, UITouch has got force property 这能让你准确地感受到在触摸事件中施加的压力。

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

    更新:

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

    诀窍是超越 hittest 在内部 窗口 扩展(可以在 UIView 水平也一样,但它会有更广泛的影响,因为 UIView公司 窗口 ),当您看到来自 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
        }
    }
    
        2
  •  0
  •   Dorukhan Arslan    6 年前

    解决办法比我想的要容易。对于iOS9+系统,我们可以按照以下步骤访问系统键盘并监听击键。。。

    首先,创建一个自定义 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 没事的。我们无法将同一类型的多个轻触手势识别器添加到视图中。