约束条件不适用于导航控制器

约束条件不适用于导航控制器

问题描述:

我会尽可能快地尝试。我有一个高度为0的容器的主视图,每当启用键盘时,我将容器设置为与键盘相同的高度,并且我有一个按钮和一个电子邮件字段,并且已经为此容器设置了约束,基本上向上推动元素。我已经将视图设置为在视图加载时启用并且其主视图正常工作,但只要按下按钮即可进入下一视图,键盘会打开,但按钮和电子邮件字段会留在键盘后面因为约束不起作用,但是当我按home按钮并关闭应用程序(而不是从后台)并重新打开它时,约束正常工作。只有当我将导航控制器嵌入主视图时才会发生这种情况,否则它会完美地工作。有任何想法吗?约束条件不适用于导航控制器

我在两个视图上都有完全相同的代码。 Ps:对不起,很长的文章,我不知道如何解释它。

@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() 
     } 
    } 
} 

更新:我发现问题的一部分。 加载第二个视图时,我无法获得键盘高度,我将第二个视图代码从“viewWillAppear”更改为“viewDidAppear”,使容器与键盘高度相同,但还有另一个问题。当我加载第一个视图时,我得到271的键盘高度(这是正确的),当我移动到第二个视图时,出于某种原因,键盘高度为226,使textField移动45.同样的事情发生在我按下返回按钮从第二个视图返回到第一个,键盘高度是226.当我按下home按钮并重新打开应用程序时,无论我是哪个屏幕都可以获得271的键盘高度,这是正确的高度。我做错了什么?

更新2:已解决!

因为我的代码只在没有导航控制器的情况下工作,我有一种感觉,这是导航控制器所具有的快速动画和转换的功能,它阻止了代码在加载前被读取,所以我试图写这个一行代码 emailTF.resignFirstResponder()我的按钮动作,它的工作!所以基本上我不得不在下一个视图中加载之前关闭键盘。我希望我能帮助一些有相同问题的用户。

首先确保包含正在更改的视图的VC是textfield/textview的委托,然后从viewWillAppear调用.becomeFirstResponder()。确保您正确注册/注销键盘通知。如果可能的话,您可以使用滚动视图(通过默认UIView)来包含ViewControllers子视图,而不是改变约束。

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 
} 
+0

我已经发现问题并更新了帖子。你提到scrollView,但在我的情况下,这将起作用,因为我想只向上移动一个元素,使用scrollView会使事情变得复杂。感谢您的帮助! –

+0

@ AlexandreD'Acol我一直觉得使用滚动视图替换视图并添加上面的可重用代码更容易。很高兴听到你解决它!照顾好你的项目并祝你好运! – RLoniello

+0

高兴地了解它,我从来没有使用过这种方法,但我一定会尝试。谢谢 ! –

使用此行代码self.view.layoutIfNeeded()而不是view.setNeedsLayout()

并确保对您得到正确的高度或没有键盘的高度。

谢谢!

+0

谢谢,但它不工作,我改变了代码行,没有任何东西。此外,键盘的高度是正确的,因为当我从视图中删除导航控制器时,它运行良好。另外,当我删除导航控制器,并从segue取消选中“animate”框时,它也不起作用。看起来有些东西阻止了加载的约束,并且当有一些动画允许约束正常工作时。 –

+0

为什么你没有选中该框?我认为限制在这种情况下不起作用。 – iDev750

+0

我只是为了测试而做的,正如我之前所说的,代码不适用于导航控制器。 –