7

How do you adjust your scrollview to compensate for a keyboard vertically? Read on...

Yes I know this is some basic info, but I randomly noticed today that all of the answers I saw about this topic are all over the place with info, versions and/or use bangs all over the place... but nothing solid for Swift 3+.

2 Answers 2

19

Swift 4.2:

Substitute scrollView for UITableView, UICollectionView, etc.

let scrollView = UIScrollView()

Add observers.

override open func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
}

Add some functions to listen for the notifications:

@objc func keyboardWillHide(notification: Notification) {
    let contentInsets = UIEdgeInsets.zero
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets
}

@objc func keyboardWillShow(notification: Notification) {
    guard let keyboardFrame: CGRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
    scrollView.contentInset.bottom = keyboardFrame.height
}

Worth noting is that if your deployment target is iOS 9 or greater, you don't need to remove the observer anymore. Check the NotificationCenter docs for more info.

deinit {
    NotificationCenter.default.removeObserver(self)
}

------------------------------------------------

Swift 3:

let scrollView = UIScrollView()

Add observers.

override open func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(noti:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    NSNotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(noti:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}

Add some functions to listen for the notifications:

func keyboardWillHide(noti: Notification) {
    let contentInsets = UIEdgeInsets.zero
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets
}

func keyboardWillShow(noti: Notification) {

    guard let userInfo = noti.userInfo else { return }
    guard var keyboardFrame: CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return }
    keyboardFrame = self.view.convert(keyboardFrame, from: nil)

    var contentInset:UIEdgeInsets = scrollView.contentInset
    contentInset.bottom = keyboardFrame.size.height
    scrollView.contentInset = contentInset
}

Worth noting is that if your deployment target is iOS 9 or greater, you don't need to remove the observer anymore. Check the NotificationCenter docs for more info.

deinit {
    NotificationCenter.default.removeObserver(self)
}
Sign up to request clarification or add additional context in comments.

Comments

7

A modification to make it work on iOS 11 is to use UIKeyboardFrameEndUserInfoKey rather than UIKeyboardFrameBeginUserInfoKey. Just a simplified approach to @crewshin's solution:

@objc func keyboardWillShow(_ notification: NSNotification) {                
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        scrollView.contentInset.bottom = keyboardSize.height
    }
}

@objc func keyboardWillHide(_ notification: NSNotification) {        
    scrollView.contentInset.bottom = 0
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.