Skip to content

Instantly share code, notes, and snippets.

@DeFrenZ
Created March 18, 2016 10:24
Show Gist options
  • Save DeFrenZ/a742fbfb4e72bb849849 to your computer and use it in GitHub Desktop.
Save DeFrenZ/a742fbfb4e72bb849849 to your computer and use it in GitHub Desktop.
//
// DZKeyboardLayoutProxyView.swift
//
// Created by Davide De Franceschi on 25/02/2015.
//
import UIKit
final class DZKeyboardLayoutProxyView: UIView {
private var keyboardObserver: NSObjectProtocol?
@IBOutlet weak var delegate: DZKeyboardLayoutProxyViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
translatesAutoresizingMaskIntoConstraints = true
startObservingKeyboardNotifications()
}
override func awakeFromNib() {
super.awakeFromNib()
frame = CGRect(x: 0, y: superview!.bounds.height, width: superview!.bounds.width, height: 0)
backgroundColor = .clearColor()
opaque = false
alpha = 0
hidden = true
}
deinit {
stopObservingKeyboardNotifications()
}
}
private let changeKeyboardAnimateLayoutDuration: NSTimeInterval = 0.2
extension DZKeyboardLayoutProxyView {
private func startObservingKeyboardNotifications() {
keyboardObserver = NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillChangeFrameNotification, object: nil, queue: nil) { [weak self] notification in
guard
let sself = self,
let notificationInfo = notification.userInfo
else { return }
let startFrame = (notificationInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
let endFrame = (notificationInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
guard endFrame != startFrame else { return }
let animationCurveOptions = UIViewAnimationOptions(rawValue: (notificationInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).unsignedLongValue)
let notificationAnimationDuration = (notificationInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue as NSTimeInterval
let animationDuration = notificationAnimationDuration > 0 ? notificationAnimationDuration : changeKeyboardAnimateLayoutDuration
let newFrame = sself.superview?.convertRect(endFrame, fromView: nil) ?? .zero
let callDelegateWillChangeFrame: () -> ()
let callDelegateDidChangeFrame: () -> ()
if let delegate = sself.delegate {
callDelegateWillChangeFrame = { delegate.keyboardProxyView(sself, willChangeFrameToFrame: newFrame) }
callDelegateDidChangeFrame = { delegate.keyboardProxyView(sself, didChangeFrameToFrame: newFrame) }
} else {
callDelegateWillChangeFrame = {}
callDelegateDidChangeFrame = {}
}
let animationOptions = animationCurveOptions ∪ .BeginFromCurrentState
let animations: () -> () = {
sself.superview?.layoutIfNeeded()
callDelegateDidChangeFrame()
}
let updateFrame: () -> () = { () -> () in
callDelegateWillChangeFrame()
sself.frame = newFrame
UIView.animateWithDuration(animationDuration, delay: 0, options: animationOptions, animations: animations, completion: nil)
return
}
dispatch_sync_main(updateFrame)
}
}
private func stopObservingKeyboardNotifications() {
if let observer = keyboardObserver {
NSNotificationCenter.defaultCenter().removeObserver(observer)
}
}
}
@objc protocol DZKeyboardLayoutProxyViewDelegate: NSObjectProtocol {
func keyboardProxyView(keyboardView: DZKeyboardLayoutProxyView, willChangeFrameToFrame frame: CGRect)
func keyboardProxyView(keyboardView: DZKeyboardLayoutProxyView, didChangeFrameToFrame frame: CGRect)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment