Last active
August 13, 2023 11:28
-
-
Save bsmith11/3cd29b093448f0fcb65871bf968cfab5 to your computer and use it in GitHub Desktop.
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
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) | |
} | |
} |
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
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