Move view with keyboard using Swift Move view with keyboard using Swift ios ios

Move view with keyboard using Swift


Here is a solution, without handling the switch from one textField to another:

override func viewDidLoad() {        super.viewDidLoad()        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)                }   func keyboardWillShow(notification: NSNotification) {                if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {        self.view.frame.origin.y -= keyboardSize.height    }            }func keyboardWillHide(notification: NSNotification) {    self.view.frame.origin.y = 0}

To solve this, replace the two functions keyboardWillShow/Hide with these:

func keyboardWillShow(notification: NSNotification) {            if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {        if view.frame.origin.y == 0 {            self.view.frame.origin.y -= keyboardSize.height        }    }        }func keyboardWillHide(notification: NSNotification) {    if view.frame.origin.y != 0 {        self.view.frame.origin.y = 0    }}

Swift 3.0:

override func viewDidLoad() {    super.viewDidLoad()                NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    }@objc func keyboardWillShow(notification: NSNotification) {            if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {        if self.view.frame.origin.y == 0 {            self.view.frame.origin.y -= keyboardSize.height        }    }        }@objc func keyboardWillHide(notification: NSNotification) {    if self.view.frame.origin.y != 0 {        self.view.frame.origin.y = 0    }}    

Swift 4.0:

override func viewDidLoad() {    super.viewDidLoad()                NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    }@objc func keyboardWillShow(notification: NSNotification) {            if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {        if self.view.frame.origin.y == 0 {            self.view.frame.origin.y -= keyboardSize.height        }    }        }@objc func keyboardWillHide(notification: NSNotification) {    if self.view.frame.origin.y != 0 {        self.view.frame.origin.y = 0    }}

Swift 4.2:

override func viewDidLoad() {    super.viewDidLoad()                NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)}@objc func keyboardWillShow(notification: NSNotification) {    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {        if self.view.frame.origin.y == 0 {            self.view.frame.origin.y -= keyboardSize.height        }    }}@objc func keyboardWillHide(notification: NSNotification) {    if self.view.frame.origin.y != 0 {        self.view.frame.origin.y = 0    }}


Easiest way that doesn't even require any code:

  1. Download KeyboardLayoutConstraint.swift and add (drag & drop) the file into your project, if you're not using the Spring animation framework already.
  2. In your storyboard, create a bottom constraint for the View or Textfield, select the constraint (double-click it) and in the Identity Inspector, change its class from NSLayoutConstraint to KeyboardLayoutConstraint.
  3. Done!

The object will auto-move up with the keyboard, in sync.


One of the popular answers on this thread uses the following code:

func keyboardWillShow(sender: NSNotification) {    self.view.frame.origin.y -= 150}func keyboardWillHide(sender: NSNotification) {    self.view.frame.origin.y += 150}

There's an obvious problem with offsetting your view by a static amount. It'll look nice on one device but will look bad on any other size configuration. You'll need to get the keyboards height and use that as your offset value.

Here's a solution that works on all devices and handles the edge-case where the user hides the predictive text field while typing.

Solution

Important to note below, we're passing self.view.window in as our object parameter. This will provide us with data from our Keyboard, such as its height!

@IBOutlet weak var messageField: UITextField!override func viewDidLoad() {    super.viewDidLoad()    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: self.view.window)    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: self.view.window)}func keyboardWillHide(sender: NSNotification) {    let userInfo: [NSObject : AnyObject] = sender.userInfo!    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size    self.view.frame.origin.y += keyboardSize.height}

We'll make it look nice on all devices and handle the case where the user adds or removes the predictive text field.

func keyboardWillShow(sender: NSNotification) {    let userInfo: [NSObject : AnyObject] = sender.userInfo!    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size    if keyboardSize.height == offset.height {        UIView.animateWithDuration(0.1, animations: { () -> Void in            self.view.frame.origin.y -= keyboardSize.height        })    } else {        UIView.animateWithDuration(0.1, animations: { () -> Void in            self.view.frame.origin.y += keyboardSize.height - offset.height        })    }}

Remove Observers

Don't forget to remove your observers before you leave the view to prevent unnecessary messages from being transmitted.

override func viewWillDisappear(animated: Bool) {    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)}

Update based on question from comments:

If you have two or more text-fields, you can check to see if your view.frame.origin.y is at zero.

func keyboardWillShow(sender: NSNotification) {    let userInfo: [NSObject : AnyObject] = sender.userInfo!    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size    if keyboardSize.height == offset.height {        if self.view.frame.origin.y == 0 {            UIView.animateWithDuration(0.1, animations: { () -> Void in                self.view.frame.origin.y -= keyboardSize.height            })        }    } else {        UIView.animateWithDuration(0.1, animations: { () -> Void in            self.view.frame.origin.y += keyboardSize.height - offset.height        })    }     print(self.view.frame.origin.y)}