Skip to content

Create a scrollview that responds to the appearance of the keyboard

Notifications You must be signed in to change notification settings

mistahenry/swift-scrollview-keyboard-example

Repository files navigation

Unfortunately, implementing a UI with textfields inside of a scrollview that allows for scrolling when the keyboard opens is not as trivial as one might imagine it to be. The solution I've developed is the Apple recommended, and it involves a combination of Storyboard development with autolayout and programmatic resizing of views upon reception of certain keyboard events (hide/show). I've chosen to use Swift, but the amount of code is small and shouldn't be hard to adapt to Obj-C if needbe.

To start, place a UIScrollview inside of the base view. We need to pin this scroll view to the base view using autolayout. I recommend using the Add New Constraints button insde of storyboard after you've clicked on the UIScrollview, using (0, 0, 0, 0) as the values for the Space to Nearest Neighbor. You could also ctrl-drag directly from to the UIScrollview to the base view and set the leading/trailing space to margins and the vertical space to top/bottom layout all to 0 (the Add New Constraints approach does just that.

Next, we place a UIView inside of the Scrollview and pin it to the UIScrollView again with the (0,0,0,0). Change the name of this UIView to ContentView in the storyboard(just so it's easy to distinguish the constraints) and give it a unique background color. Now here comes the trick: we need the ContentView to be constrained to the base view, not the scrollview. The scrollview adjusts to the size of what's inside of it, so constraining what is inside of it to the scrollview itself creates ambiguity in the auto layout calculations. Give the ContentView Equal Width and Height to the base view by ctrl-dragging from between the two and set those constraints in the storyboard.

Now, just for proving this works, we are going to vertically center a single Text Field inside of the ContentView. Do this by creating two constraints against the content view: Center Vertically and Horizontally in the container. Lastly, give the text field a fixed width of say 200 by clicking on it, Add New Constraints->Width. If you were to run the simulator now, you would see a vertically centered fixed with text field that adapts to screen rotations, but not yet to keyboard appearance.

Now, we have to do view resizing according to Apple based on the showing/hiding of the keyboard. Inside the ViewController that is backing this View in the storyboard, we need to create an IBOutlet so we can reference it. Easiest way for me to do this is to open the split view, and ctrl drag from the UIScrollView to the View Ctrl, Insert Outlet, and name the variable scrollView. You should see the following added to the top of the ViewController file:

@IBOutlet weak var scrollView: UIScrollView!

Next, in the viewDidLoad function, after the super call, we need to handle two keyboard events:

NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
        
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

You'll probably get some errors now that the selector doesn't exist, so lets add the two selector fn's we've defined to handle the events:

func keyboardDidShow(notification: NSNotification) {
   if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
       let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)
       self.scrollView.contentInset = contentInsets
       self.scrollView.scrollIndicatorInsets = contentInsets
    }
}
    
func keyboardWillBeHidden(notification: NSNotification) {
    let contentInsets = UIEdgeInsets.zero
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
}

What we are effectively doing is adjusting the contentInset property of the Scrollview to account for the fact that there is a keyboard that has appeared by adjusting this property based on the keyboard's size info that we receive in the Notifications.

Now, run the simulator, and you should be able to scroll the whole view once the keyboard is open. Hope this helps :)

About

Create a scrollview that responds to the appearance of the keyboard

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages