skip to Main Content

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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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)
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search