Created
August 29, 2018 22:05
-
-
Save RustyKnight/3f5e10808442dc2a6e52bfa56018a1a5 to your computer and use it in GitHub Desktop.
Extension to display the view when keyboard is presented
This file contains hidden or 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
import Foundation | |
import UIKit | |
// I'm not a fan of this, but this will allow us to maintain state beyond the capabailities of the the extension API | |
fileprivate var cache = NSHashTable<UIViewController>(options: .weakMemory) | |
extension UIViewController { | |
fileprivate var isInstalled: Bool { | |
return cache.contains(self) | |
} | |
var displaceOnKeyboard: Bool { | |
set { | |
if newValue { | |
guard !isInstalled else { | |
return | |
} | |
cache.add(self) | |
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDisplacerWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) | |
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDisplacerWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) | |
} else { | |
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil) | |
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) | |
cache.remove(self) | |
} | |
} | |
get { | |
return isInstalled | |
} | |
} | |
fileprivate func keyboardBounds(from notification: Notification, forKey key: String) -> CGRect? { | |
guard let userInfo = notification.userInfo else { | |
return nil | |
} | |
guard let keyboardHeight = userInfo[key] as? CGRect else { | |
return nil | |
} | |
return keyboardHeight | |
} | |
fileprivate func keyboardEndBounds(from notification: Notification) -> CGRect? { | |
return keyboardBounds(from: notification, forKey: UIResponder.keyboardFrameEndUserInfoKey) | |
} | |
fileprivate func keyboardBeginingBounds(from notification: Notification) -> CGRect? { | |
return keyboardBounds(from: notification, forKey: UIResponder.keyboardFrameBeginUserInfoKey) | |
} | |
@objc func keyboardDisplacerWillShow(_ notification: Notification) { | |
guard let view = view else { | |
return | |
} | |
guard let userInfo = notification.userInfo else { | |
return | |
} | |
guard let endBounds = keyboardEndBounds(from: notification) else { | |
return | |
} | |
var frame = view.frame | |
var needsDisplacement = true | |
guard frame.origin.y != -endBounds.height else { | |
return | |
} | |
// Only display the view if the keyboard covers the current responder | |
if let currentResponder = view.firstResponder { | |
let rect = currentResponder.convert(currentResponder.frame, to: view) | |
needsDisplacement = endBounds.contains(rect) | |
} | |
guard needsDisplacement else { | |
return | |
} | |
guard let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double, | |
let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else { | |
frame.origin.y -= endBounds.height | |
view.frame = frame | |
return | |
} | |
UIView.animate(withDuration: duration, delay: 0, options: [UIView.AnimationOptions(rawValue: curve)], animations: { | |
frame.origin.y -= endBounds.height | |
view.frame = frame | |
}) { (completed) in | |
} | |
} | |
@objc func keyboardDisplacerWillHide(_ notification: Notification) { | |
guard let view = view else { | |
return | |
} | |
guard let userInfo = notification.userInfo else { | |
return | |
} | |
var frame = view.frame | |
guard let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double, | |
let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else { | |
frame.origin.y = 0 | |
view.frame = frame | |
return | |
} | |
UIView.animate(withDuration: duration, delay: 0, options: [UIView.AnimationOptions(rawValue: curve)], animations: { | |
frame.origin.y = 0 | |
view.frame = frame | |
}) { (completed) in | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment