Mo Code
Mo Code

Reputation: 117

Swift move scroll view up when keyboard present

I'm working on an iOS app and currently all my elements are in a scroll view and when the keyboard is present I move the view up 250 pts. This solved my problem but the keyboard is always a different size per device.

How could I detect how far from the bottom of the screen my text field is and how tall the keyboard is?

Upvotes: 0

Views: 1294

Answers (3)

Mudith Chathuranga Silva
Mudith Chathuranga Silva

Reputation: 7434

I'm currently work on this and found a solution. First you need to add a notification to the view controller to identify whether the keyboard is on or not. For that you need to register this notification in viewDidLoad().

override func viewDidLoad() { 
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardDidShow:", name: UIKeyboardWillChangeFrameNotification, object: nil)
}

And also don't forget to remove this notification, when the view controller removed from the view. So remove this notification on viewDidDisappear().

 override func viewDidDisappear(animated: Bool) { 
     NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillChangeFrameNotification, object: nil)
 }

And the final thing is to manage the scroll view when the keyboard is on or off. So first you need to identify the keyboard height.Then for pretty smooth animation, you can use keyboard animation mood and duration time to animate your scroll view.

func keyboardDidShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
        let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue
        let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
        if endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height {
            //isKeyboardActive = false
            UIView.animateWithDuration(duration,
            delay: NSTimeInterval(0),
            options: animationCurve,
            animations: { 
             // move scroll view height to 0.0 
             },
            completion: { _ in
        })
        } else {
            //isKeyboardActive = true
            UIView.animateWithDuration(duration,
            delay: NSTimeInterval(0),
            options: animationCurve,
            animations: { 
             // move scroll view height to    endFrame?.size.height ?? 0.0 
             },
            completion: { _ in
        })
        }
    }
}

Upvotes: 1

Julien Quere
Julien Quere

Reputation: 2459

@noir_eagle answer seems right.

But there may be is a simpler solution. Maybe you could try using IQKeyboardManager. It allows you to handle these keyboard things in a simple and seamless way.

I think you really should, at least, spend few minutes looking at it.

Upvotes: 0

haik.ampardjian
haik.ampardjian

Reputation: 864

You should observe the notification for showing and hiding the keyboard. And after that you can get the exact keyboard size and either shift or change the content insets of your scroll view. Here's a sample code:

extension UIViewController {
    func registerForKeyboardDidShowNotification(scrollView: UIScrollView, usingBlock block: (NSNotification -> Void)? = nil) {
        NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
            let userInfo = notification.userInfo!
            let keyboardSize = userInfo[UIKeyboardFrameBeginUserInfoKey]?.CGRectValue.size
            let contentInsets = UIEdgeInsetsMake(scrollView.contentInset.top, scrollView.contentInset.left, keyboardSize!.height, scrollView.contentInset.right)

            scrollView.scrollEnabled = true
            scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
            block?(notification)
        })
    }

    func registerForKeyboardWillHideNotification(scrollView: UIScrollView, usingBlock block: (NSNotification -> Void)? = nil) {
        NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillHideNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
            let contentInsets = UIEdgeInsetsMake(scrollView.contentInset.top, scrollView.contentInset.left, 0, scrollView.contentInset.right)
            scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
            scrollView.scrollEnabled = false
            block?(notification)
        })
    }
}

extension UIScrollView {
    func setContentInsetAndScrollIndicatorInsets(edgeInsets: UIEdgeInsets) {
        self.contentInset = edgeInsets
        self.scrollIndicatorInsets = edgeInsets
    }
}

And in your UIViewController in which you want to shift the scrollview, just add next lines under the viewDidLoad() function

override func viewDidLoad() {
    super.viewDidLoad()

    registerForKeyboardDidShowNotification(scrollView)
    registerForKeyboardWillHideNotification(scrollView)
}

Upvotes: 2

Related Questions