【问题标题】:Constraints not working with Navigation Controller约束不适用于导航控制器
【发布时间】:2017-12-02 17:30:39
【问题描述】:

我会尽可能快。我有一个高度为 0 的容器的主视图,每当启用键盘时,我都会将容器设置为与键盘相同的高度,并且我有一个按钮和一个电子邮件字段,并且我已经为这个容器设置了约束,基本上将元素向上推。我已将键盘设置为在加载视图时启用,并且它在主视图中正常工作,但只要我按下按钮转到下一个视图,键盘就会打开,但按钮和电子邮件字段留在键盘后面因为约束不起作用,但是当我按下主页按钮并关闭应用程序(不是从后台)并重新打开它时,约束正常工作。这只发生在我将导航控制器嵌入到主视图中时,否则它可以完美地工作。有什么想法吗?

我在两个视图上都有完全相同的代码。 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。当我按下主页按钮并重新打开应用程序时,无论我是哪个屏幕,我得到的键盘高度为 271,这是正确的高度.我做错了什么?

更新 2:已解决!

因为我的代码只能在没有导航控制器的情况下工作,所以我感觉它与导航控制器的快速动画和过渡有关,并且它阻止了在加载之前读取代码,所以我尝试编写这一行代码 emailTF.resignFirstResponder() 我的按钮操作,它起作用了!所以基本上我必须先关闭键盘,然后再将其加载到下一个视图中。我希望我能帮助一些遇到同样问题的用户。

【问题讨论】:

    标签: ios swift keyboard constraints navigationcontroller


    【解决方案1】:

    首先确保包含正在更改的视图的 VC 是文本字段/文本视图的委托,然后从 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
    }
    

    【讨论】:

    • 我已经发现了问题并更新了帖子。您提到了 scrollView 但在我的情况下这会起作用,因为我只想向上移动一个元素并且使用 scrollView 会使事情复杂化。感谢您的帮助!
    • @AlexandreD'Acol 我一直觉得用滚动视图替换视图并添加上面的可重用代码更容易。很高兴听到你修好了!保重,祝你的项目好运!
    • 很高兴知道它,我从未使用过这种方法,但我一定会尝试。谢谢!
    【解决方案2】:

    使用这行代码 self.view.layoutIfNeeded() 代替 view.setNeedsLayout()

    并确保您的键盘高度是否正确。

    谢谢!

    【讨论】:

    • 谢谢,但它不起作用,我更改了代码行,但什么也没有。键盘的高度也是正确的,因为当我从视图中删除导航控制器时,它运行良好。此外,当我删除导航控制器并取消选中 segue 中的“动画”框时,它也不起作用。看起来有些东西阻止了约束加载,当有一些动画时,它允许约束正常工作。
    • 我这样做只是为了测试,正如我之前所说,代码不适用于导航控制器。
    • 我不明白的是,没有导航控制器怎么能完美运行?这很奇怪。
    • 能否分享完整的代码?这样我就可以运行并修复它。
    • 我刚刚测试并看到函数@objc func keyboardWillShow(_ notification: Notification) 没有在第二个视图上被调用,从而阻止容器具有相同的键盘高度。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多