Skip to content

Instantly share code, notes, and snippets.

@juliengdt
Last active August 29, 2015 14:27
Show Gist options
  • Save juliengdt/43205e21df1234042608 to your computer and use it in GitHub Desktop.
Save juliengdt/43205e21df1234042608 to your computer and use it in GitHub Desktop.
Auto-Scroll in Swift, wherever you want, everywhere - not perfect but works like a charm
extension UIView {
//MARK: - AutoScroll Stuff -
private func autoScroll(view: UIView, kbFrame: CGRect, animated: Bool) {
let offset = kbFrame.height + 20
let deltaOffset = CGRectGetMinY(view.convertRect(view.bounds, toView: self.view)) - offset
autoScrollOffset = deltaOffset < 0 ? 0 : deltaOffset
totalAutoScrollOffset = autoScrollOffset
if autoScrollOffset > 0 {
UIView.animateWithDuration(animated ? 0.3 : 0, animations: {
self.view.transform(y: -self.autoScrollOffset)
}, completion: { (finished) -> Void in
self.autoScrollAnimating = false
})
}else {
autoScrollAnimating = false
}
}
private func resetAutoScroll(animated: Bool) {
if totalAutoScrollOffset > 0 {
UIView.animateWithDuration(animated ? 0.3 : 0, animations: {
self.view.transform(y: self.autoScrollOffset)
}, completion: { (finished) -> Void in
self.autoScrollAnimating = false
})
}else {
autoScrollAnimating = false
}
totalAutoScrollOffset = 0
}
func willautoScrollOffset(notification: NSNotification){
if !inhibitAutoScroll {
guard let kbInfo = notification.userInfo else { return }
guard let kbFrame = kbInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
guard let firstRespView = self.view.findFirstResponder() else { return }
keyboardFrame = kbFrame.CGRectValue()
if !autoScrollAnimating {
autoScrollAnimating = true
autoScroll(firstRespView, kbFrame: keyboardFrame, animated: true)
}
}
}
func willautoScrollReset(notification: NSNotification){
if !inhibitAutoScroll {
autoScrollAnimating = true
resetAutoScroll(true)
}
}
func findFirstResponder() -> UIView? {
if self.isFirstResponder() {
return self
}
for subview in subviews {
if let respView = subview.findFirstResponder() {
return respView
}
}
return self
}
func transform(x: CGFloat? = 0, y: CGFloat? = 0, width: CGFloat? = 0, height: CGFloat? = 0){
self.frame = CGRectMake(self.frame.origin.x + x!, self.frame.origin.y + y!, self.frame.width + width!, self.frame.height + height!)
}
}
// Place this into your viewWillAppear() motherBaseViewController:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "willautoScrollOffset:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "willautoScrollReset:", name: UIKeyboardWillHideNotification, object: nil)
}
//Place this into your viewWillDisappear motherBaseViewController
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
//Why viewWillAppear/Disappear instead of viewDidLoad/deinit ?
//because with this method, you avoid glitch-scrolling when you push another view containing a scrollView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment