Skip to content

Instantly share code, notes, and snippets.

@joshavant
Created September 13, 2018 22:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshavant/56f3abdfad0e5ac0bdc6ea3c0913f555 to your computer and use it in GitHub Desktop.
Save joshavant/56f3abdfad0e5ac0bdc6ea3c0913f555 to your computer and use it in GitHub Desktop.
//
// KeyboardInsettable.swift
//
// Created by Josh Avant on 9/11/18.
//
import Foundation
import UIKit
protocol KeyboardInsettable {
var keyboardInsettableScrollView: UIScrollView { get }
static var defaultScrollViewContentInset: UIEdgeInsets { get }
func registerForKeyboardNotifications(willChangeFrameSelector selector: Selector)
func handleKeyboardWillChangeFrame(notification: Notification)
}
// NOTE: Does not support adjustable iPad keyboard.
extension KeyboardInsettable {
func registerForKeyboardNotifications(willChangeFrameSelector selector: Selector) {
NotificationCenter.default.addObserver(self, selector: selector, name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
func handleKeyboardWillChangeFrame(notification: Notification) {
guard let keyboardFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber,
let animationCurve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber,
let window = UIApplication.shared.keyWindow,
let superview = self.keyboardInsettableScrollView.superview else { return }
let scrollViewYMinimum = window.convert(self.keyboardInsettableScrollView.frame, from: superview).minY
let scrollViewYMaximum = scrollViewYMinimum + self.keyboardInsettableScrollView.frame.height
let scrollViewYCoordinateRange = scrollViewYMinimum..<scrollViewYMaximum
let keyboardYMinimum = keyboardFrame.origin.y
let keyboardYMaximum = keyboardYMinimum + keyboardFrame.size.height
let keyboardYCoordinateRange = keyboardYMinimum..<keyboardYMaximum
let overlappingYCoordinateRange = scrollViewYCoordinateRange.clamped(to: keyboardYCoordinateRange)
let overlapAmount = overlappingYCoordinateRange.upperBound - overlappingYCoordinateRange.lowerBound
let newContentInsets = UIEdgeInsets(top: Self.defaultScrollViewContentInset.top,
left: Self.defaultScrollViewContentInset.left,
bottom: Self.defaultScrollViewContentInset.bottom + overlapAmount,
right: Self.defaultScrollViewContentInset.right)
let newIndicatorInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: overlapAmount, right: 0.0)
let curve = UIViewAnimationOptions(rawValue: animationCurve.uintValue)
UIView.animate(withDuration: animationDuration.doubleValue, delay: 0, options: curve, animations: {
self.keyboardInsettableScrollView.contentInset = newContentInsets
self.keyboardInsettableScrollView.scrollIndicatorInsets = newIndicatorInsets
}, completion: nil)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment