【问题标题】:Input Accessory View Behave Unexpectedly with keyboard hide and show events输入附件视图行为异常与键盘隐藏和显示事件
【发布时间】:2018-07-16 06:05:22
【问题描述】:

我在使用 InputAccessoryView 时遇到了一个奇怪的行为,我正在使用 InputAccessoryView 的聊天屏幕上工作,我已经注册了 KeyboardWillShowKeyboardWillHide 通知。当我的聊天屏幕出现时,它会自动调用一次KeyboardWillShowMethod,之后它会自动隐藏而不调用KeyboardWillHide 通知。加载聊天后,当我单击文本框输入文本时,它调用KeyboardWillShow,这很好。但是当我尝试隐藏键盘时,它首先调用两个方法,它会调用KeyboardWillHide,然后它会调用KeyboardWillShow,这很奇怪。

这是我隐藏键盘时的聊天屏幕Image。 这是显示键盘的时候Image

我正在以编程方式使用此InputAccessoryView 代码inputAccessoryView

这就是我注册键盘通知的方式。

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

 @objc func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            var contentInset = self.collectionView?.contentInset
            contentInset?.bottom = keyboardSize.maxY
            self.collectionView?.contentInset = contentInset!
            self.collectionView?.scrollIndicatorInsets = contentInset!
          //  collectionViewBottomAnchor?.constant = keyboardSize.height + 50

//            print ("input height  \(inputAccessoryView?.frame.maxY) ")
//            print("keyboard height \(keyboardSize.height)")
//            print("keyboard Y \(keyboardSize.maxY)")
//            print("keyboard Y \(keyboardSize.minY)")
            //print("keyboard Y \(inputAccessoryView.framemaxY)")


            if self.messages.count > 0{
                UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                    self.view.layoutIfNeeded()

                }, completion: { (completed:Bool) in
                    let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
                    self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)

                })
            }
        }
    }

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

            print("keyboard hide")
          self.collectionView?.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 52, right: 0)

            self.collectionView?.scrollIndicatorInsets = UIEdgeInsets(top: 8, left: 0, bottom: 52, right: 0)
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                self.view.layoutIfNeeded()

            }, completion: { (completed:Bool) in

            })
        }
    }

在选择器中,我试图根据键盘的 Y 索引更改我的 CollectionView 插入,因为我没有得到键盘的高度,这也是一个问题。键盘高度始终为 inputAccessoryView 高度的 50。

【问题讨论】:

  • 显示您的选择器代码。
  • @RakeshaShastri 我已经用选择器方法更新了问题。
  • 试试UIKeyboardFrameBeginUserInfoKey,而不是UIKeyboardFrameEndUserInfoKey
  • 如果它对您的场景有帮助,也请检查:stackoverflow.com/questions/47286239/…
  • 嘿@Amit 谢谢。它有很大帮助。

标签: swift keyboard-events inputaccessoryview


【解决方案1】:

这是我为@Amit 找到的解决方案。我没有使用UIKeyboardFrameBeginUserInfoKey,而是使用了UIKeyboardFrameEndUserInfoKey,在这样做之后,我能够在KeyboardWillAppear方法中获得准确的键盘高度。现在剩下的问题是KeyboardWillShow 方法在KeyboardWillHide 之后被调用,但当时KeyboardWillShow 的键盘高度为50。 这意味着当我尝试隐藏键盘时,它会调用 KeyboardWillHide,这很好,之后它会自动调用 KeyboardWillShow,但键盘的高度仍然是 50,所以我把条件放在那里。

现在下面的方法只有在高度大于50时才会生效。

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

        if keyboardSize.height > 50{
                var contentInset = self.collectionView?.contentInset
                contentInset?.bottom = keyboardSize.height + 50
                self.collectionView?.contentInset = contentInset!
                self.collectionView?.scrollIndicatorInsets = contentInset!


            if self.messages.count > 0{
                UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                    self.view.layoutIfNeeded()

                }, completion: { (completed:Bool) in
                                        let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
                                        self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)

                })
            }
        }

    }
}

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

            self.collectionView?.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 52, right: 0)
            self.collectionView?.scrollIndicatorInsets = UIEdgeInsets(top: 0, left: 0, bottom: 52, right: 0)
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                self.view.layoutIfNeeded()

            }, completion: { (completed:Bool) in

            })
        }
    }

【讨论】:

    【解决方案2】:

    当键盘有输入附件视图时,keyboardDidHideNotification被观察两次:

    1. 键盘隐藏时。
    2. 当输入附件视图被隐藏时(注意输入附件视图在键盘关闭后的一段时间内可见)。

    如果您的实现依赖于仅调用一次的选择器,您可以执行以下解决方法之一:

    选项 A:检查键盘框架:

    @objc
    private func keyboardDidHide(_ notification: Notification) {
        guard let keyboardRect = notification.keyboardRect, keyboardRect.origin.y == view.frame.maxY else {
            return
        }
        // Do whatever you need...
    }
    
    extension Notification {
        var keyboardRect: CGRect? {
            guard let keyboardSize = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {
                return nil
            }
            return keyboardSize.cgRectValue
        }
    }
    

    选项 B:使用 GDC 的油门反应:

    private var pendingKeyboardDidHideRequestWorkItem: DispatchWorkItem?
    
    private func keyboardDidHide(_ notification: Notification) {
        pendingKeyboardDidHideRequestWorkItem?.cancel()
    
        let keyboardDidHideRequestWorkItem = DispatchWorkItem { [weak self] in
            // Do whatever you need...
        }
    
        pendingKeyboardDidHideRequestWorkItem = keyboardDidHideRequestWorkItem
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500), execute: keyboardDidHideRequestWorkItem)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-08
      相关资源
      最近更新 更多