Search code examples
iosswiftviewkeyboardtextfield

Keyboard covers text fields at the bottom of my view


I have searched

here: Move a view up only when the keyboard covers an input field

here: Move textfield when keyboard appears swift

here: How to make a UITextField move up when keyboard is present?

and here: https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

Unfortunately, all of the links and seemingly everywhere else I can find do not give a good clean solution that I am looking for. They are either outdated with Obj-c code, or plain do not work in the current iteration of Xcode 9 with Swift 4.

How do I manage a keyboard that is covering text fields at the bottom of my view? I want the screen's view to move only when they keyboard is covering the text field view, without using a scroll view, with the ability to animate this to make it look pretty rather than have it just snap, and most importantly I do not want to use an outside library.

CoreAnimation libraries from Apple are great and all, but all of the sample code is outdated and in objective c which is deprecated at this point (I cannot believe that Apple isn't updating their documentation).

If someone could point me in the right direction to updated and current code or a library from Apple I am missing that will specifically address this issue, it would be much appreciated.


Solution

  • This code will work, making your textField animating to above keyboard if its frame intersects with that of keyboard and animating back to original position on keyboard hide.

    @IBOutlet weak var textField: UITextField!
    
      var offsetY:CGFloat = 0
    
      override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
      }
    
      func keyboardFrameChangeNotification(notification: Notification) {
        if let userInfo = notification.userInfo {
          let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect
          let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0
          let animationCurveRawValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int) ?? Int(UIViewAnimationOptions.curveEaseInOut.rawValue)
          let animationCurve = UIViewAnimationOptions(rawValue: UInt(animationCurveRawValue))
          if let _ = endFrame, endFrame!.intersects(self.textField.frame) {
            self.offsetY = self.textField.frame.maxY - endFrame!.minY
            UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
              self.textField.frame.origin.y = self.textField.frame.origin.y - self.offsetY
            }, completion: nil)
          } else {
            if self.offsetY != 0 {
              UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
                self.textField.frame.origin.y = self.textField.frame.origin.y + self.offsetY
                self.offsetY = 0
              }, completion: nil)
            }
          }
        }
      }