Last active
March 1, 2019 16:33
-
-
Save scotteg/1f1c027a229fca6b723993000f69152c to your computer and use it in GitHub Desktop.
Drop-in keyboard handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// HandlesKeyboard.swift | |
// | |
// Created by Scott Gardner on 1/14/19. | |
// Copyright © 2019 Scott Gardner. All rights reserved. | |
// | |
import UIKit | |
protocol HandlesKeyboard where Self: UIViewController { | |
var bottomConstraintForKeyboardHandling: NSLayoutConstraint! { get } | |
func startHandlingKeyboardChanges() | |
func stopHandlingKeyboardChanges() | |
} | |
extension HandlesKeyboard { | |
/// Registers caller to start handling keyboard will show and will hide notifications | |
/// - Warning: Caller *must* implement `stopHandlingKeyboardChanges()` to unregister, e.g., in `deinit` | |
/// ``` | |
/// func stopHandlingKeyboardChanges() { | |
/// NotificationCenter.default.removeObserver(self) | |
/// } | |
/// | |
/// deinit { | |
/// stopHandlingKeyboardChanges() | |
/// } | |
/// ``` | |
func startHandlingKeyboardChanges() { | |
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { [weak self] in | |
self?.updateBottomConstraint(notification: $0) | |
} | |
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { [weak self] in | |
self?.updateBottomConstraint(notification: $0) | |
} | |
} | |
// Intentionally not implemented to ensure caller unregisters | |
// func stopHandlingKeyboardChanges() { | |
// NotificationCenter.default.removeObserver(self) | |
// } | |
func updateBottomConstraint(notification: Notification) { | |
guard let userInfo = notification.userInfo, | |
let animationDuration = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue, | |
let keyboardEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue, | |
let rawAnimationCurve = (userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value | |
else { return } | |
if notification.name == UIResponder.keyboardWillHideNotification { | |
bottomConstraintForKeyboardHandling.constant = 0.0 | |
} else { | |
bottomConstraintForKeyboardHandling.constant = view.bounds.maxY - view.convert(keyboardEndFrame, to: view.window).minY | |
} | |
let animationCurve = UIView.AnimationOptions(rawValue: UInt(rawAnimationCurve << 16)) | |
UIView.animate(withDuration: animationDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: { [weak self] in | |
self?.view.layoutIfNeeded() | |
}, completion: nil) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment