Last active
August 25, 2016 08:23
-
-
Save RyogaK/1458bd43a2c0ea7d88aa9480fe9ed549 to your computer and use it in GitHub Desktop.
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
// | |
// UIViewController+ScrollWhenKeyboardAppear.swift | |
// LIFE | |
// | |
// Created by Ryoga Kitagawa on 8/8/16. | |
// Copyright © 2016 Givery Inc. All rights reserved. | |
// | |
import Foundation | |
extension UIViewController { | |
func startKeyboardAvoiding() { | |
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UIViewController.scrollTextFieldWhehKeybordShown(_:)), name: UIKeyboardWillShowNotification, object: nil) | |
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UIViewController.restoreScrollTextField(_:)), name: UIKeyboardWillHideNotification, object: nil) | |
} | |
func endKeyboardAvoidance() { | |
NSNotificationCenter.defaultCenter().removeObserver(self) | |
} | |
@objc func scrollTextFieldWhehKeybordShown(notification: NSNotification) { | |
guard let textField = self.view.currentFirstResponder() as? UIView, | |
scrollView = textField.findSuperView(UIScrollView.self), | |
userInfo = notification.userInfo, | |
keyboardFrame = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue, | |
animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue | |
else { return } | |
let margin = keyboardMarginForResponderView(textField) | |
let maxOffset = scrollView.contentSize.height - scrollView.bounds.height + keyboardFrame.height | |
let origOffset = scrollView.contentOffset | |
scrollView.contentInset = UIEdgeInsetsZero | |
scrollView.scrollIndicatorInsets = UIEdgeInsetsZero | |
let convertedKeyboardFrame = scrollView.convertRect(keyboardFrame, fromView: nil) | |
let convertedTextFieldFrame = textField.convertRect(textField.bounds, toView: scrollView) | |
let diffOfOffsetY = convertedTextFieldFrame.maxY - convertedKeyboardFrame.minY + margin | |
if diffOfOffsetY > 0 { | |
UIView.animateWithDuration(animationDuration) { | |
let offsetY = min(diffOfOffsetY + origOffset.y, maxOffset) | |
let insetsY = max(diffOfOffsetY + origOffset.y - maxOffset, 0) | |
let contentInsets = UIEdgeInsetsMake(0, 0, insetsY, 0) | |
scrollView.contentInset = contentInsets | |
scrollView.scrollIndicatorInsets = contentInsets | |
scrollView.contentOffset = CGPointMake(0, offsetY) | |
} | |
} | |
} | |
@objc func restoreScrollTextField(notification: NSNotification) { | |
guard let textField = self.view.currentFirstResponder() as? UIView, | |
let scrollView = textField.findSuperView(UIScrollView.self) | |
else { return } | |
scrollView.contentInset = UIEdgeInsetsZero | |
scrollView.scrollIndicatorInsets = UIEdgeInsetsZero | |
} | |
func keyboardMarginForResponderView(view: UIView) -> CGFloat { | |
return 8 | |
} | |
} | |
private extension UIView { | |
func currentFirstResponder() -> UIResponder? { | |
if self.isFirstResponder() { | |
return self | |
} | |
for view in self.subviews { | |
if let responder = view.currentFirstResponder() { | |
return responder | |
} | |
} | |
return nil | |
} | |
func insertTextToCurrentField(text: String) { | |
guard let field = self.currentFirstResponder() as? UIKeyInput else { return } | |
field.insertText(text) | |
} | |
func findSuperView<T>(ofType: T.Type) -> T? { | |
if let s = self.superview { | |
switch s { | |
case let s as T: | |
return s | |
default: | |
return s.findSuperView(ofType) | |
} | |
} | |
return nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment