Andrea Miotto Andrea Miotto - 11 months ago 101
iOS Question

iOS keyboard and Textfields

Evening, I have an app with several

, like always, when I press on a textfield I have the keyboard's position issue.

I know that I have to solve it with delegates and the
textFieldDidBeginEditing func
, to move up the textfield of
and than down again.

But usually I did it with with an easy layout, in this one there are severals nested
stack views
and I really don't know how to fix this. I read that I should use
scroll view
, I've tried but it screw up all the layout. Tips? I like so much the coding challenges but when it's about layout stuff, the hate come outside and my brain freeze.

The Layout of the App


In Auto Layout

1 Add a screen sized view on top of all

2 Add constraints to the new view

  • Leading edge equal to leading edge of superview.

  • Bottom edge equal to bottom edge of superview.

  • Equal widths with superview.

  • Equal heights with superview.

3 Make the proper constraints adjustments on the subViews/StackViews

4 Set all the textfield with delegates on the view controller

In Code - ViewController

class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var mainViewBottomConstraint: NSLayoutConstraint!
var activeField: UITextField?

override func viewDidLoad() {

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

//we are tracking the Field we are working on
func textFieldDidBeginEditing(_ textField: UITextField) {
activeField = textField

func textFieldDidEndEditing(_ textField: UITextField)
activeField = nil

func keyboardWillShow(notification: NSNotification) {
if let userInfoDict = notification.userInfo, let keyboardFrameValue = userInfoDict[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardFrame = keyboardFrameValue.cgRectValue

//The view will scroll up only for the following textfield

if activeField == zipCodetext || activeField == cityText || activeField == streetAddresstext || activeField == stateText {

UIView.animate(withDuration: 0.8) {
self.mainViewBottomConstraint.constant = keyboardFrame.size.height


func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.8) {
self.mainViewBottomConstraint.constant = 0

Thanks to @vacawama

Answer Source

Try putting your entire layout in a screen sized view, and then just moving that view up by the right amount when the keyboard appears.

Drag out a UIView and place it in your top level view. Resize it to be the size of the screen.

Set 4 constraints:

  1. Leading edge equal to leading edge of superview.
  2. Bottom edge equal to bottom edge of superview.
  3. Equal widths with superview.
  4. Equal heights with superview.

Create an @IBOutlet to the bottom constraint. When the keyboard appears, set bottomConstraint.constant = 250 to move the view up. Set it back to 0 to move it back down again. You might need a negative value for the constant depending on the ordering of the items in your constraint.

To animate the move, call layoutIfNeeded on self.view in the block for UIView.animateWithDuration:

bottomContraint.constant = 250
UIView.animateWithDuration(1.0) {