TODO: WIP. Need to test next time I integrate this.
See Greg Heo's video ScrollView tutorial on raywenderlich.com.
Text boxes can get covered up by the keyboard, especially on 3.5 inch screens (4s). The first step is to embed the page contents inside a UIScrollView.
@IBOutlet weak var scrollview: UIScrollView!Call scrollRectToVisible to bring a view out from under the keyboard.
scrollview.scrollRectToVisible(myTextView.frame, animated: true)It's a lot of boilerplate, but sometimes you just need to shift the whole thing up and down with the keyboard.
First hook into the keyboard notifications in viewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
keyboardHeightRegisterNotifications()
}Wire up a selector for UIKeyboardWillShowNotification and UIKeyboardWillHideNotification. Don't forget the : because we need to access the userInfo object.
func keyboardHeightRegisterNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}A good neighbor always cleans up after his dog.
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}Each selector we defined takes a NSNotification parameter. For each one, just call a helper method and pass in a Bool to indicate up or down.
func keyboardWillShow(notification: NSNotification) {
adjustInsetForKeyboardShow(true, notification: notification)
}
func keyboardWillHide(notification: NSNotification) {
adjustInsetForKeyboardShow(false, notification: notification)
}Now to actually move the thing up and down. Grab the keyboard height from the NSNotification and move the scrollview contentInset up or down.
To spare us from some gotchas down the road, we don't actually move the keyboard down (show ? 1 : -1) -- rather we just zero out the state.
func adjustInsetForKeyboardShow(show: Bool, notification: NSNotification) {
let adjustmentHeight = getKeyboardHeight(notification) * (show ? 1 : 0)
scrollview.contentInset.bottom = adjustmentHeight
scrollview.scrollIndicatorInsets.bottom = adjustmentHeight
}Lots of helper functions. This one unwraps the keyboard height from the NSNotification object. It's important to use the UIKeyboardFrameEndUserInfoKey from userInfo. Don't use UIKeyboardFrameBeginUserInfoKey, or you'll find yourself driving a car using your rearview mirror.
func getKeyboardHeight(notification: NSNotification) -> CGFloat{
let userInfo = notification.userInfo ?? [:]
let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
return CGRectGetHeight(keyboardFrame)
}import UIKit
class ViewController: UIViewController {
@IBOutlet weak var scrollview: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
keyboardHeightRegisterNotifications()
}
func keyboardHeightRegisterNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardWillShow(notification: NSNotification) {
adjustInsetForKeyboardShow(true, notification: notification)
}
func keyboardWillHide(notification: NSNotification) {
adjustInsetForKeyboardShow(false, notification: notification)
}
func adjustInsetForKeyboardShow(show: Bool, notification: NSNotification) {
let adjustmentHeight = getKeyboardHeight(notification) * (show ? 1 : 0)
scrollview.contentInset.bottom = adjustmentHeight
scrollview.scrollIndicatorInsets.bottom = adjustmentHeight
}
func getKeyboardHeight(notification: NSNotification) -> CGFloat{
let userInfo = notification.userInfo ?? [:]
let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
return CGRectGetHeight(keyboardFrame)
}
}