当键盘显示为Swift 4时,为什么堆栈视图会在3秒后消失?

时间:2018-02-21 10:51:16

标签: ios keyboard swift4

在屏幕底部,我有一个stackView,里面有TextView。文本视图将becomeFirstResponder() viewDidLoad()。我想要的是,键盘是我提到的下面显示了stackView。

这是我的代码:

override func viewDidLoad() {
    super.viewDidLoad()

    textView.becomeFirstResponder()
    self.hideKeyboardWhenTappedAround() //here will hide the keyboard

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

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {

        if let window = self.view.window?.frame {
            // We're not just minusing the kb height from the view height because
            // the view could already have been resized for the keyboard before
            self.view.frame = CGRect(x: self.view.frame.origin.x,
                                    y: self.view.frame.origin.y,
                                    width: self.view.frame.width,
                                    height: window.origin.y + window.height - keyboardSize.height)
            }

        }
    }

 @objc func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {

            let viewHeight = self.view.frame.height
            self.view.frame = CGRect(x: self.view.frame.origin.x,
                                     y: self.view.frame.origin.y,
                                     width: self.view.frame.width,
                                     height: viewHeight + keyboardSize.height)
        }
    }

应用上面的代码后,会显示键盘。我提到stackView在键盘上方3秒钟。然后底部的stackView消失。即使我隐藏键盘, stackView也从未表现出来。

我完全不知道发生了什么。有人请说明我的代码出了什么问题

2 个答案:

答案 0 :(得分:1)

你可以尝试

override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {

        self.viewBotCon.constant = -1 * keyboardSize.height

        self.view.layoutIfNeeded()

    }        
}

@objc func keyboardWillHide(notification: NSNotification) {

      self.viewBotCon.constant = 0

      self.view.layoutIfNeeded()
}

答案 1 :(得分:0)

尝试尽可能使用自动布局。最好将frame和bounds属性视为readonly。

实际上最好的方法

  1. 从堆栈视图底部到安全区域设置约束,并通过IBOutlet将其公开给您。

  2. 我建议您订阅UIKeyboardWillChangeFrame - 然后您也可以对键盘上的更改做出反应。

  3. 使用窗口坐标空间计算键盘的所有交点:let stackViewFrame = stackView.convert(stackView.bounds, to: nil)

  4. 计算键盘和stackview之间的交集:let intersection = keyboardFrame.intersection(stackViewFrame)

  5. 将约束的常量调整为交点+偏移:constraint.constant = intersection.size.height + offset

  6. 从通知let duration = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey].floatValue

  7. 获取动画时间
  8. 并使用动画更新布局:UIView.animate(withDuration: duration) {self.view.layoutIfNeeded() }

  9. PS:您订阅了viewDidLoad中的通知,并且从不取消订阅。这意味着如果你有任何其他后续场景,你的viewcontroller也会对它们作出反应,消耗性能并可能导致缺陷。最好在viewWillAppear中订阅键盘通知并在viewDidDisappear中取消订阅。

    PSS:对你的技能来说,使用块而不是选择器来订阅会更好。