3

The Question:

I have a ViewController that has a subclass with a UIScrollView in it.

In the scrollView there are 3 UITextFields. 2 of them with a numberPad keyboard and 1 with a UIPickerView keyboard.

The problem is that when the keyboards are presented, it hides the UITextFields. So what I'm trying to do is to move the UIViewController's view up when the keyboards are being shown.

What I've already tried:

I've searched this question on SO and I've found some answers, based on them I've wrote this code:

override func viewDidLoad() {
    super.viewDidLoad()

    //Keyboard notifications
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

//MARK: - keyboards

@objc fileprivate func keyboardWillShow(notification: Notification) {
    self.changeViewOriginBasedOnKeyboardPosition(notification: notification)
}

@objc fileprivate func keyboardWillHide(notification: Notification) {
    self.changeViewOriginBasedOnKeyboardPosition(notification: notification)
}

fileprivate func changeViewOriginBasedOnKeyboardPosition(notification: Notification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardAnimationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! TimeInterval
        UIView.animate(withDuration: keyboardAnimationDuration != 0 ? keyboardAnimationDuration : 0.2, animations: {
            if self.controllerContentView.frame.origin.y == 0  {
                self.controllerContentView.frame.origin.y = -keyboardSize.height
            } else {
                self.controllerContentView.frame.origin.y = 0
            }
        })
    }
}

fileprivate func dismissKeyboard() {
    self.view.endEditing(true)
}

//Touch handling

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.dismissKeyboard()
}

The problem with what I've tried:

Sometimes it works great, but sometimes the view "jumps" back up/"jumps" down and I can't understand why.

Does anybody see any problem with my code that can cause this bug?

Thank you!

FS.O6
  • 1,394
  • 2
  • 20
  • 42
  • please have a look this answer https://stackoverflow.com/a/40249707/3266248 – mihatel Dec 07 '17 at 16:08
  • You're setting the `frame` on the `controllerContentView` but if there's an AutoLayout update, those constraints will take over. Instead, change the constraints of `controllerContentView` and then call `view.setNeedsLayout()` inside a `UIView.animate` block. – Paolo Dec 07 '17 at 16:09

2 Answers2

1

I use a CocoaPod for this called IQKeyboardManager.

https://github.com/hackiftekhar/IQKeyboardManager

It is dead simple to set up and works globally.

Zane Campbell
  • 150
  • 1
  • 12
0

You need to set height as per your keyboard hide. There is four observer for Keyboard available.

1) UIKeyboardWillShow
2) UIKeyboardDidShow
3) UIKeyboardWillHide
4) UIKeyboardDidHide

You need to register keyboard observer:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardShowNotification), name:NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardHideNotification), name:NSNotification.Name.UIKeyboardWillHide, object: nil)

Here is method observer method:

func keyboardShowNotification(notification:NSNotification){

    var userInfo = notification.userInfo!
    var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    keyboardFrame = self.view.convert(keyboardFrame, from: nil)

    var contentInset:UIEdgeInsets = YOUR_SCROLLVIEW_OBJ.contentInset
    contentInset.bottom = keyboardFrame.size.height
    YOUR_SCROLLVIEW_OBJ.contentInset = contentInset
}

func keyboardHideNotification(notification:NSNotification){
    let contentInset:UIEdgeInsets = UIEdgeInsets.zero
    YOUR_SCROLLVIEW_OBJ = contentInset
}

Another best key to handle keyboard is IQKeyboardManager. You just have to add them to your application and it will handle everything.

Nirmalsinh Rathod
  • 5,079
  • 4
  • 26
  • 56