Forked from kristopherjohnson/KeyboardNotification.swift
Last active
August 7, 2019 10:13
-
-
Save jasorod/911055436950459021bc6a988534d9be to your computer and use it in GitHub Desktop.
Swift convenience wrapper for the userInfo values associated with a UIKeyboard notification
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 UIKit | |
/// Wrapper for the NSNotification userInfo values associated with a keyboard notification. | |
/// | |
/// It provides properties that retrieve userInfo dictionary values with these keys: | |
/// | |
/// - UIKeyboardFrameBeginUserInfoKey | |
/// - UIKeyboardFrameEndUserInfoKey | |
/// - UIKeyboardAnimationDurationUserInfoKey | |
/// - UIKeyboardAnimationCurveUserInfoKey | |
public struct KeyboardNotification { | |
let notification: Notification | |
let userInfo: [AnyHashable : Any] | |
/// Initializer | |
/// | |
/// :param: notification Keyboard-related notification | |
public init(_ notification: Notification) { | |
self.notification = notification | |
if let userInfo = notification.userInfo { | |
self.userInfo = userInfo | |
} else { | |
self.userInfo = [:] | |
} | |
} | |
/// Start frame of the keyboard in screen coordinates | |
public var screenFrameBegin: CGRect { | |
if let value = userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue { | |
return value.cgRectValue | |
} | |
else { | |
return .zero | |
} | |
} | |
/// End frame of the keyboard in screen coordinates | |
public var screenFrameEnd: CGRect { | |
if let value = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue { | |
return value.cgRectValue | |
} | |
else { | |
return .zero | |
} | |
} | |
/// Keyboard animation duration | |
public var animationDuration: Double { | |
if let number = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber { | |
return number.doubleValue | |
} | |
else { | |
return 0.25 | |
} | |
} | |
/// Keyboard animation curve | |
/// | |
/// Note that the value returned by this method may not correspond to a | |
/// UIViewAnimationCurve enum value. For example, in iOS 7 and iOS 8, | |
/// this returns the value 7. | |
public var animationCurve: UInt { | |
if let number = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber { | |
return UInt(number.intValue) | |
} | |
return UInt(UIViewAnimationCurve.easeInOut.rawValue) | |
} | |
/// Start frame of the keyboard in coordinates of specified view | |
/// | |
/// :param: view UIView to whose coordinate system the frame will be converted | |
/// :returns: frame rectangle in view's coordinate system | |
public func frameBeginForView(view: UIView) -> CGRect { | |
return view.convert(screenFrameBegin, from: view.window) | |
} | |
/// End frame of the keyboard in coordinates of specified view | |
/// | |
/// :param: view UIView to whose coordinate system the frame will be converted | |
/// :returns: frame rectangle in view's coordinate system | |
public func frameEndForView(view: UIView) -> CGRect { | |
return view.convert(screenFrameEnd, from: view.window) | |
} | |
} |
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
// Example of using KeyboardNotification to update an NSLayoutConstraint | |
import UIKit | |
final class ViewController: UIViewController { | |
// Outlet for a layout constraint that specifies distance from bottom of | |
// a subview to the bottom of the view. | |
// | |
// This constraint will be updated when the keyboard appears, disappears, | |
// or changes size. | |
@IBOutlet weak var bottomLayoutConstraint: NSLayoutConstraint! | |
override func viewWillAppear(animated: Bool) { | |
super.viewWillAppear(animated) | |
NSNotificationCenter.defaultCenter().addObserver(self, | |
selector: "keyboardWillChangeFrameNotification:", | |
name: UIKeyboardWillChangeFrameNotification, | |
object: nil) | |
} | |
override func viewDidDisappear(animated: Bool) { | |
NSNotificationCenter.defaultCenter().removeObserver(self) | |
super.viewDidDisappear(animated) | |
} | |
func keyboardWillChangeFrameNotification(notification: NSNotification) { | |
let n = KeyboardNotification(notification) | |
let keyboardFrame = n.frameEndForView(self.view) | |
let animationDuration = n.animationDuration | |
let animationCurve = n.animationCurve | |
let viewFrame = self.view.frame | |
let newBottomOffset = viewFrame.maxY - keyboardFrame.minY | |
self.view.layoutIfNeeded() | |
UIView.animateWithDuration(animationDuration, | |
delay: 0, | |
options: UIViewAnimationOptions(rawValue: animationCurve), | |
animations: { | |
self.bottomLayoutConstraint.constant = newBottomOffset | |
self.view.layoutIfNeeded() | |
}, | |
completion: nil | |
) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated for Swift 4