Handle another app's obscuring keyboard on iPad split view (iOS 9 multitasking)

时间:2016-04-15 14:52:59

标签: ios ipad keyboard multitasking splitview

Previously if one presented a keyboard on one's own app one would embed everything in a UIScrollView and adjust the contentInset to keep content from being obscured by the keyboard.

Now with split view multitasking on iOS 9 the keyboard may appear at any moment and stay visible even while the user is no longer interacting with the other app.

Question

Is there an easy way to adapt all view controllers that were not expecting the keyboard to be visible and without start embedding everything in scrollviews?

1 个答案:

答案 0 :(得分:0)

秘诀是收听每当键盘在您的应用中显示/隐藏时触发的UIKeyboardWillChangeFrame通知,或者从与您并排运行的其他应用中隐藏的通知。

我创建了此扩展程序,以便轻松启动/停止观察这些事件(我在viewWillAppear / Disappear中调用它们),并轻松获取通常用于obscuredHeight的{​​{1}}调整表/集合/滚动视图的底部contentInset

@objc protocol KeyboardObserver
{
    func startObservingKeyboard() // Call this in your controller's viewWillAppear
    func stopObservingKeyboard() // Call this in your controller's viewWillDisappear
    func keyboardObscuredHeight() -> CGFloat
    @objc optional func adjustLayoutForKeyboardObscuredHeight(_ obscuredHeight: CGFloat, keyboardFrame: CGRect, keyboardWillAppearNotification: Notification) // Implement this in your controller and adjust your bottom inset accordingly
}

var _keyboardObscuredHeight:CGFloat = 0.0;

extension UIViewController: KeyboardObserver
{
    func startObservingKeyboard()
    {
        NotificationCenter.default.addObserver(self, selector: #selector(observeKeyboardWillChangeFrameNotification(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    func stopObservingKeyboard()
    {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    func observeKeyboardWillChangeFrameNotification(_ notification: Notification)
    {
        guard let window = self.view.window else {
            return
        }

        let animationID = "\(self) adjustLayoutForKeyboardObscuredHeight"
        UIView.beginAnimations(animationID, context: nil)
        UIView.setAnimationCurve(UIViewAnimationCurve(rawValue: (notification.userInfo![UIKeyboardAnimationCurveUserInfoKey]! as AnyObject).intValue)!)
        UIView.setAnimationDuration((notification.userInfo![UIKeyboardAnimationCurveUserInfoKey]! as AnyObject).doubleValue)

        let keyboardFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue
        _keyboardObscuredHeight = window.convert(keyboardFrame!, from: nil).intersection(window.bounds).size.height
        let observer = self as KeyboardObserver
        observer.adjustLayoutForKeyboardObscuredHeight!(_keyboardObscuredHeight, keyboardFrame: keyboardFrame!, keyboardWillAppearNotification: notification)

        UIView.commitAnimations()
    }

    func keyboardObscuredHeight() -> CGFloat
    {
        return _keyboardObscuredHeight
    }
}