Skip to content

Instantly share code, notes, and snippets.

@matthiasnys
Last active September 20, 2017 14:14
Show Gist options
  • Save matthiasnys/a9d4ce7d6bd997a2153f4bad77263857 to your computer and use it in GitHub Desktop.
Save matthiasnys/a9d4ce7d6bd997a2153f4bad77263857 to your computer and use it in GitHub Desktop.
A Keyboard helper for your Swift Keyboard troubles.
//
// NYSKeyboardHelper.swift
// B-NYS GCV
//
// Created by Matthias on 18/03/2017.
// https://gist.github.com/matthiasnys/a9d4ce7d6bd997a2153f4bad77263857#file-nyskeyboardhelper-swift-L6
// Copyright © 2017 B-NYS. All rights reserved.
//
import UIKit
class NYSKeyboardHelper: NSLayoutConstraint {
@IBInspectable var extraIndent: CGFloat = 0.0
private var lastNotification: Notification? = nil
override init() {
super.init()
setup()
}
private func setup() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidChangeVisible(notification:)), name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidChangeVisible(notification:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidChangeVisible(notification:)), name: .UIKeyboardDidShow, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
}
/// This can be called to update the constraint if the view moves (without keyboard appearing/disappearing)
/// Should be used in a popoverviewcontroller -> viewWillLayoutSubviews
func update() {
if let notification = lastNotification {
keyboardDidChangeVisible(notification: notification)
}
}
@objc private func keyboardDidChangeVisible(notification: Notification) {
guard let firstItem = self.firstItem as? UIView else {
print("NYSKEYBOARDHELPER: Fist item needs to be a UIView")
return
}
guard let superview = firstItem.superview else {
print("NYSKEYBOARDHELPER: Fist item needs a superview of the type UIView")
return
}
var animationDuration: TimeInterval = 0.0
var animationOptions: UIViewAnimationOptions = UIViewAnimationOptions(rawValue: 0)
var endFrame = CGRect.zero
if let animationCurve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? UIViewAnimationCurve {
animationOptions = UIViewAnimationOptions(rawValue: UInt(animationCurve.rawValue << 16))
}
if let animationDurationFromUserInfo = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? TimeInterval {
animationDuration = animationDurationFromUserInfo
}
if let endFrameFromUserInfo = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect {
endFrame = endFrameFromUserInfo
}
let contentAbsoluteFrame = superview.convert(firstItem.frame, to: nil) //To nil -> On the Window
let offset = contentAbsoluteFrame.maxY - endFrame.minY + extraIndent
let keyboardHeight = max(0, offset)
animationOptions = UIViewAnimationOptions(rawValue: animationOptions.rawValue | UIViewAnimationOptions.layoutSubviews.rawValue)
lastNotification = notification
UIView.animate(withDuration: animationDuration, delay: 0.0, options: animationOptions, animations: {
self.constant = keyboardHeight
firstItem.layoutIfNeeded()
}, completion: nil)
}
}
@matthiasnys
Copy link
Author

Initialise using:
self.view.addConstraint(NYSKeyboardHelper(item: self.view, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1.0, constant: 0.0))

@matthiasnys
Copy link
Author

If you use it in a popover, be sure to call update when the frame of your contentview has changed!
So:
-> viewWillLayoutSubview -> Call update on the keyboardhandler

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment