Keyboard covers text fields at the bottom of my view

爱⌒轻易说出口 提交于 2019-12-04 09:50:35

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)
        }
      }
    }
  }

You can use IQKeyboardManagerSwift to solve your issue easily and fast.

Use below pod in your pod file Which give support to Swift 4.

pod 'IQKeyboardManagerSwift', '5.0.0'

Here is link to implement IQKeyboardManagerSwift.

https://github.com/hackiftekhar/IQKeyboardManager

Thanks!!!

This piece of code worked for me.

In case of multiple textfields

I have implemented only for the textfields which are at the bottom (without using notification observer).

If you are using scrollView, this code might be helpful (scrollViewDidScroll is optional)

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentSize = CGSize(width: self.scrollView.frame.size.width, height: (scrollView.frame.size.height + 300))// To be more specific, I have used multiple textfields so wanted to scroll to the end.So have given the constant 300.
}

func textFieldDidBeginEditing(_ textField:UITextField) {
    self.scrollView.setContentOffset(textField.frame.origin, animated: true)
}

and if you want to set the textfields position according to the view, try this:

func textFieldDidBeginEditing(_ textField:UITextField){
    textField.frame.origin.y = textField.frame.origin.y - 150 //(If have not used contentsizing the scroll view then exclude this line)default origin takes the texfield to the top of the view.So to set lower textfields to proper position have used the constant 150.
    self.scrollView.setContentOffset(textField.frame.origin, animated: true)
}

To do specifically for textfields at the bottom. Check their tag value textfield.tag in textFieldDidBeginEditing

func textFieldDidBeginEditing(_ textField:UITextField){
    if textField.tag = 4 { //tag value of the textfield which are at the bottom
        self.scrollView.setContentOffset(textField.frame.origin, animated: true)
    }
}

If you implemented textfields in tableView go with notification observer which is explained below.

If there are multiple textfields in a tableView preferably go with Notification Observer

override func viewDidAppear(_ animated: Bool) {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.2, animations: {
        // For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
        self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    })
}

deinit {
    print("denit")
    NotificationCenter.default.removeObserver(self)
}

Add an extensio to Uiview:

import UIKit

//Binding view to keyboard changes extension UIView {

func bindToKeyboard(){
    NotificationCenter.default.addObserver(self, selector: #selector(UIView.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}



@objc func keyboardWillChange(_ notification: NSNotification) {
    let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
    let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
    let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let deltaY = targetFrame.origin.y - curFrame.origin.y

    UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
        self.frame.origin.y += deltaY

    },completion: {(true) in
        self.layoutIfNeeded()
    })
}

}

worked perfectly for me: http://www.seemuapps.com/move-uitextfield-when-keyboard-is-presented

If delegates are set right,

 func textFieldDidBeginEditing(_ textField: UITextField) {
        moveTextField(textField, moveDistance: -250, up: true)
    }

    // Finish Editing The Text Field
    func textFieldDidEndEditing(_ textField: UITextField) {
        moveTextField(textField, moveDistance: -250, up: false)
    }

    // Hide the keyboard when the return key pressed
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

    // Move the text field in a pretty animation!
    func moveTextField(_ textField: UITextField, moveDistance: Int, up: Bool) {
        let moveDuration = 0.3
        let movement: CGFloat = CGFloat(up ? moveDistance : -moveDistance)

        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(moveDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!