iOS – Resizing the ScrollView on keyboard appearance

While building an iOS app recently, we struggled a bit to resize the scroll view on keyboard appearance. Since the solution is not so straight, we decided to document it for everyone else to use.

This is how it looks like:

ezgif.com-video-to-gif.gif

 

And here’s how we did it-

In your ViewController implement UITextFieldDelegate. In viewDidLoad() add following code:

        //Setting delegate for textfield
        myFirstTextField.delegate = self
        mySecondTextField.delegate = self

Add following optional variable to the ViewController:

        /* this will hold the current text field being edited */
        var currentTextField:UITextField?
        /* this will hold the contentoffset of the scrollview before resizing of the scrollview, this will be used to restore the content offset of scroll view when keyboard is hidden */
        var lastOffset:CGPoint?
        //this will hold the height of keyboard
        var keyboardHeight:CGFloat?

We need to add following two actions from UITextFieldDelegate:

        func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        currentTextField = textField
        lastOffset = self.scrollView.contentOffset
        return true
        }
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        currentTextField?.resignFirstResponder()
        currentTextField = nil
        return true
        }

Now add following two observers:

        @objc func keyboardWillShow(notification: NSNotification) {
        if keyboardHeight != nil {
        return
        }
        //UIKeyboardFrameBeginUserInfoKey
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size {
        keyboardHeight = keyboardSize.height
        UIView.animate(withDuration: 0.3, animations: {
        self.constraintContentHeight.constant += self.keyboardHeight!
        })
        let distanceToBottom = self.scrollView.frame.size.height - (currentTextField?.frame.origin.y)! - (currentTextField?.frame.size.height)!
        let collapseSpace = keyboardHeight! - distanceToBottom
        if collapseSpace < 0 {
        return
        }
        UIView.animate(withDuration: 0.3, animations: {
        //Your scrollview will scroll to 5 coordinates above the keyboard
        self.scrollView.contentOffset = CGPoint(x: (self.lastOffset?.x)!, y: collapseSpace + 5)
        })
        }
        }
        @objc func keyboardWillHide(notification: NSNotification) {
        if self.keyboardHeight != nil{
        UIView.animate(withDuration: 0.3) {
        self.constraintContentHeight.constant -= self.keyboardHeight!
        self.scrollView.contentOffset = self.lastOffset!
        }
        keyboardHeight = nil
        }
        }

In viewDidLoad() add two functions as observers:

    //Adding observers
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: Notification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: Notification.Name.UIKeyboardWillHide, object: nil)