简体   繁体   中英

View is getting shifted every time I re-tap textfield

so I have a small app where I choose an image, get it into an image view and I have 2 textfield to insert a funny phrase

(Meme editor app) my problem is since the bottom textfield is covered when the keyboard is shown I had to shift the view upwards every time the keyboard is shown for the bottom texfield and I succeed in doing that, what goes wrong is that every time I re-tap the beginning or the end of an existing text in the text filed the view shifts up again in undesirable behavior

here is a small GIF that shows what happens exactly

here is my code so far:

Function to get Kyboard height:

func getKeyboardHeight(_ notification:Notification) -> CGFloat {
        let userInfo = notification.userInfo
        let keyboardSize = userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue // of CGRect
        return keyboardSize.cgRectValue.height
    }

Function to shift the view up in the condition that bottom textfield is what the user taps

@objc func keyboardWillShow(_ notification:Notification) {
        if bottomTextField.isFirstResponder{
            view.frame.origin.y -= getKeyboardHeight(notification)
        }
    }

Function to return the view to its normal position when the user finishes editing the bottom text field

@objc func keyboardWillHide(_ notification:Notification) {
    view.frame.origin.y = 0
}

Functions to add and remove observers of keyboard notifications

func subscribeToKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    }

func subscribekeyboardWillHide() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

func unsubscribeFromKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    }

func unsubscribekeyboardWillHide() {
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    }

and where I call them

override func viewWillAppear(_ animated: Bool) {
    
    super .viewWillAppear(true)
    cameraButton.isEnabled = UIImagePickerController.isSourceTypeAvailable(.camera)
    subscribeToKeyboardNotifications()
    subscribekeyboardWillHide()
    
}

override func viewWillDisappear(_ animated: Bool) {
    
    super.viewWillDisappear(animated)
    unsubscribeFromKeyboardNotifications()
    unsubscribekeyboardWillHide()
    
}

if you could be kind to provide a simple explanation for your solution I would appreciate it

Every time you change the cursor location, UIResponder.keyboardWillShowNotification notification triggered, thats why every time you tap the textfield it moves up one keyboard height more.

You can use UIResponder.keyboardDidShowNotification notification instead of UIResponder.keyboardWillShowNotification . This one is not triggered when cursor location changes.

This is what I do while managing keyboard. It causes no problems.

Declare in your UIViewController class

private let notificationCenter = NotificationCenter.default

then in

 override func viewDidLoad() {
        super.viewDidLoad()
        notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
        notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }

This is the adjust for keyboard function

@objc private func adjustForKeyboard(notification: Notification) {
        guard let userInfo = notification.userInfo else { return }
        guard let keyboardScreenEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
        let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
        if notification.name == UIResponder.keyboardWillHideNotification {
            scrollView.contentInset = UIEdgeInsets.zero
        } else {
            scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0)
        }
        scrollView.scrollIndicatorInsets = scrollView.contentInset
    }

Deinit here -

 override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(true)

        notificationCenter.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
        notificationCenter.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }

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