简体   繁体   中英

Moving UITextFields when keyboard shows

I am trying to move UITextFields when the Keyboard shows. Now I've seen videos and read articles on how to do it. I haven't seen one that uses the textfield itself, rather they use the bottom constraint of the textfield. Here is a video of what my code does, below is my code.

class ViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var nameTF: UITextField!
@IBOutlet weak var emailTF: UITextField!

var selectedTextField: UITextField?

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    createKeyboardNotification()
}

func createKeyboardNotification() {
    NotificationCenter.default.addObserver(self, selector: #selector(respondToKeyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(respondToKeyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

@objc func respondToKeyboardWillShow(notification: Notification) {
    adjustHeightForTextFields(isKeyboardHidden: false, notification: notification, textField: selectedTextField)
}

@objc func respondToKeyboardWillHide(notification: Notification) {
   adjustHeightForTextFields(isKeyboardHidden: true, notification: notification, textField: selectedTextField)
}


func adjustHeightForTextFields(isKeyboardHidden: Bool, notification: Notification, textField: UITextField?) {

    guard let userInfo = notification.userInfo else { return }
    let keyboardFrameRect = userInfo[UIKeyboardFrameEndUserInfoKey] as! CGRect

    if let textField = textField {
        let textFieldYPosition = textField.frame.origin.y

        if view.frame.maxY - textFieldYPosition > keyboardFrameRect.height {
            UIView.animate(withDuration: 0.25) {
                textField.frame.origin.y = (self.view.frame.maxY - textField.frame.size.height - keyboardFrameRect.height - 8)
            }
        }
        else {
            UIView.animate(withDuration: 0.25) {
                let difference = textFieldYPosition - keyboardFrameRect.height
                textField.frame.origin.y = difference + 16 + self.view.safeAreaInsets.bottom - 8
            }
        }
    }
}

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

func textFieldDidBeginEditing(_ textField: UITextField) {
    switch textField {
    case nameTF:
        print("NAME")
        selectedTextField = nameTF
        break
    case emailTF:
        print("EMAIL")
        selectedTextField = emailTF
        break
    default:
        break
    }
}
}

If you have seen the video, I've come across some strange things. First when you tap on the textfield it works like its suppose to, but when you start typing the textfield just disappears. I didn't come across this when I was using the textfield bottom constraint. Now the second part is when the keyboard is already shown the textfield doesn't animate correctly, until you click it twice.

Now I am not using a scrollview, but would like to push the whole content or would I need to use a scrollview. If you take a look at this video , you can better understand what I mean by wanting to push the content.

Would really appreciate any help provided, Thanks. :)

You need to move the view up only when the textField on the bottom becomes active.

//Create a global variable to use as our keyboardHeight
var keyboardHeight: CGFloat = 0.0

override func viewDidLoad() {
        super.viewDidLoad()

    //Set the delegate only for the emailTF
    emailTF.delegate = self

    //Set up an observer. This will help us calculate keyboard height dynamically, depending on the iPhone the app runs on.
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}

@objc private func keyboardWillShow(notification: NSNotification) {
    if let keyboardRectValue = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        keyboardHeight = keyboardRectValue.height
    }
}

Then move the view up and down when the textField becomes active/inactive.

func textFieldDidBeginEditing(_ textField: UITextField) {
        print("MOVE VIEW UP")
        if self.view.frame.origin.y == 0{
            self.view.frame.origin.y -= keyboardHeight
        }
}

func textFieldDidEndEditing(_ textField: UITextField) {
        print("MOVE VIEW DOWN")
        if self.view.frame.origin.y != 0{
            self.view.frame.origin.y += keyboardHeight
        }
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        print("MOVE VIEW DOWN")
        if self.view.frame.origin.y != 0{
            self.view.frame.origin.y += keyboardHeight
        }
    return true
}

This should definitely work. Good luck!

I agree that it's not clear always. We do this in our app and we used a scroll view. We embed the entire page in the scroll view. Then we move the bottom of the scroll view up. Scrollviews are easy to implement.

@objc func keyboardWillShow(notification: NSNotification) {
    // Only deal with this if the window is active and visible.
    if !self.isViewLoaded || self.view.window == nil {
        return
    }
    if let userInfo = notification.userInfo {
        let keyboardFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as! CGRect
        scrollView.frame = CGRect(x: view.frame.origin.x,y: view.frame.origin.y,width: view.frame.width, height: view.frame.height - keyboardFrame.height - 64)

     }
    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)))
}

And when the keyboard disappears:

@objc func keyboardWillHide(notification: NSNotification) {
    scrollView.frame = scrollViewOriginalFrame
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM