Skip to content

Instantly share code, notes, and snippets.

@bsmith11
Last active August 13, 2023 11:28
Show Gist options
  • Save bsmith11/3cd29b093448f0fcb65871bf968cfab5 to your computer and use it in GitHub Desktop.
Save bsmith11/3cd29b093448f0fcb65871bf968cfab5 to your computer and use it in GitHub Desktop.
import UIKit
import Anchorage
protocol KeyboardAdjustable {
}
extension KeyboardAdjustable where Self: UIViewController {
var keyboardLayoutGuide: UILayoutSupport {
return keyboardLayoutGuideObject
}
func configureWithBottomLayoutGuide(bottomLayoutGuide: UILayoutSupport) {
let layoutGuide = keyboardLayoutGuideObject
if !view.layoutGuides.contains(layoutGuide) {
view.addLayoutGuide(layoutGuide)
layoutGuide.bottomAnchor == bottomLayoutGuide.topAnchor
layoutGuide.horizontalAnchors == view.horizontalAnchors
}
}
}
// MARK: - Private
private extension KeyboardAdjustable where Self: UIViewController {
var keyboardLayoutGuideObject: KeyboardLayoutGuideObject {
guard let object = objc_getAssociatedObject(self, &KeyboardLayoutGuideObject.associatedKey) as? KeyboardLayoutGuideObject else {
let object = KeyboardLayoutGuideObject()
objc_setAssociatedObject(self, &KeyboardLayoutGuideObject.associatedKey, object, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return object
}
return object
}
}
// MARK: - KeyboardLayoutGuide
class KeyboardLayoutGuideObject: UILayoutGuide, UILayoutSupport {
static var associatedKey = "com.bradsmith.keyboardLayoutGuideObjectAssociatedKey"
private var heightConstraint: NSLayoutConstraint?
var length: CGFloat {
return layoutFrame.height
}
override init() {
super.init()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillUpdate(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillUpdate(_:)), name: UIKeyboardWillHideNotification, object: nil)
heightConstraint = heightAnchor == 0.0
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
}
// MARK: - Private
private extension KeyboardLayoutGuideObject {
@objc func keyboardWillUpdate(notification: NSNotification) {
let animationCurve = (notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.unsignedIntegerValue ?? 0
let animationDuration = (notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0.0
let keyboardFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() ?? CGRect.zero
let keyboardVisible = notification.name == UIKeyboardWillShowNotification
let options = UIViewAnimationOptions(rawValue: animationCurve << 16)
let animations: () -> Void = { [weak self] in
self?.heightConstraint?.constant = keyboardVisible ? keyboardFrame.height : 0.0
self?.owningView?.layoutIfNeeded()
}
UIView.animateWithDuration(animationDuration, delay: 0.0, options: options, animations: animations, completion: nil)
}
}
import UIKit
import Anchorage
protocol KeyboardAdjustable {
}
extension KeyboardAdjustable where Self: UIViewController {
var keyboardLayoutGuide: UILayoutSupport {
return keyboardLayoutGuideObject
}
func configureWithBottomLayoutGuide(bottomLayoutGuide: UILayoutSupport) {
let layoutGuide = keyboardLayoutGuideObject
if !view.subviews.contains(layoutGuide) {
view.addSubview(layoutGuide)
layoutGuide.bottomAnchor == bottomLayoutGuide.topAnchor
layoutGuide.horizontalAnchors == view.horizontalAnchors
}
}
}
// MARK: - Private
private extension KeyboardAdjustable where Self: UIViewController {
var keyboardLayoutGuideObject: KeyboardLayoutGuideObject {
guard let object = objc_getAssociatedObject(self, &KeyboardLayoutGuideObject.associatedKey) as? KeyboardLayoutGuideObject else {
let object = KeyboardLayoutGuideObject(frame: .zero)
objc_setAssociatedObject(self, &KeyboardLayoutGuideObject.associatedKey, object, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return object
}
return object
}
}
// MARK: - KeyboardLayoutGuide
class KeyboardLayoutGuideObject: UIView, UILayoutSupport {
static var associatedKey = "com.bradsmith.keyboardLayoutGuideObjectAssociatedKey"
private var heightConstraint: NSLayoutConstraint?
var length: CGFloat {
return bounds.height
}
override init(frame: CGRect) {
super.init(frame: frame)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillUpdate(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillUpdate(_:)), name: UIKeyboardWillHideNotification, object: nil)
heightConstraint = heightAnchor == 0.0
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
}
// MARK: - Private
private extension KeyboardLayoutGuideObject {
@objc func keyboardWillUpdate(notification: NSNotification) {
let animationCurve = (notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.unsignedIntegerValue ?? 0
let animationDuration = (notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0.0
let keyboardFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() ?? CGRect.zero
let keyboardVisible = notification.name == UIKeyboardWillShowNotification
let options = UIViewAnimationOptions(rawValue: animationCurve << 16)
let animations: () -> Void = { [weak self] in
self?.heightConstraint?.constant = keyboardVisible ? keyboardFrame.height : 0.0
self?.superview?.layoutIfNeeded()
}
UIView.animateWithDuration(animationDuration, delay: 0.0, options: options, animations: animations, completion: nil)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment