简体   繁体   中英

Constraints not working with Navigation Controller

I will try to be as quick as I can. I have a Main view with a container with a height of 0 and whenever the keyboard is enabled I set the container to be the same height of the keyboard and I have aa button and a email field and I have set constraints to this container, basically pushing the elements up. I have set the keyboard to be enabled when the view is loaded and its working normal with he main view but as soon as I press the button to go to the next view, the keyboard opens but the buttons and the email field stay behind the keyboard because the constraints are not working, but when I press the home button and close the app (not from the background) and re open it, the constraints work normally. This only happens when I embed a navigation controller to the main view, otherwise its perfectly working. Any ideas?

I have the exact same code on both Views. Ps: Sorry for the long post, I had no idea how to explain it.

@IBOutlet weak var emailTF: UITextField!

@IBOutlet weak var bottomHeight: NSLayoutConstraint!`

override func viewWillAppear(_ animated: Bool)
{
    super.viewWillAppear(animated)

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

    // Show keyboard by default
    emailTF.becomeFirstResponder()
}

@objc func keyboardWillShow(_ notification: Notification)
{
       if let userInfo = notification.userInfo
    {
        if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
            bottomHeight.constant = keyboardSize.height
            view.setNeedsLayout()
        }
    }
}

Update: I found part of the problem. When loading the second view I wasn't able to get the keyboard height, I changed the second view code from "viewWillAppear" to "viewDidAppear", making the container the same as the keyboard height, BUT there is another issue. When I load the first view I get the keyboard height of 271 (which is correct), when I move to the second view the keyboard height is 226 for some reason, making the textField to move 45. The same thing happens when I press the back button to go back from the secondView to the first, the keyboard height is 226. When I press the home button and reopen the app it doesn't matter which screen I am I get the keyboard height of 271, which is the correct height. What I am doing wrong?

Update 2: SOLVED!

Because my code was only working without the navigation controller I had a feeling that it was something with the quick animation and transition the navigation controller had and it was preventing the code to be read before loading, so I tried to write this line of code emailTF.resignFirstResponder() to my button action and it worked! So basically I had to dismiss the keyboard before loading it up in the next view. I hope I helped some users having the same issue.

first ensure that the VC containing the view that is being changed is the delegate of the textfield/textview then call .becomeFirstResponder() from viewWillAppear. Make sure you are registering/deregistering keyboard notifications properly. If at all possible, you can use a scroll view (over the default UIView) to contain the ViewControllers subviews instead of altering constraints.

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillShow, object: nil, queue: nil, using: keyboardWasShown)
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillHide, object: nil, queue: nil, using: keyboardWillBeHidden)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillHide, object: nil)
}

func keyboardWasShown(notification: Notification) -> Void {
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    var keyboardSize:CGRect = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    if keyboardSize.size.height <= 0 { // to fix bug on iOS 11
        keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    }
    self.scrollView.contentInset.bottom = keyboardSize.height //add this much
    self.scrollView.scrollIndicatorInsets.bottom = keyboardSize.height //scroll too it.

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height
    if let activeField = self.activeTextView {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

func keyboardWillBeHidden(notification: Notification){
    self.scrollView.contentInset.bottom = 0
    self.scrollView.isScrollEnabled = true
    self.scrollView.alwaysBounceVertical = true
}

Use this line of code self.view.layoutIfNeeded() instead of view.setNeedsLayout()

And make sure about the height of keyboard that you are getting correct height or not.

Thanks!

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