【问题标题】:How to adjust bottom constraint in the middle of "drag down" keyboard of .interactive keyboardDismissMode collection view?如何在 .interactive keyboardDismissMode 集合视图的“向下拖动”键盘中间调整底部约束?
【发布时间】:2021-06-25 09:59:56
【问题描述】:

我希望实现键盘和视图调整大小的行为,如 iOS 消息中所示。它看起来像

https://i.imgur.com/92rvHpo.mp4

我尝试以下方法

步骤 1

这确保了当我们的向下滚动手势触及键盘区域时,键盘将随着我们的手势动作向下滚动。

collectionView.keyboardDismissMode = .interactive

第二步

调整底部约束,以确保我们的集合视图不会被键盘在视觉上阻挡。当键盘完成隐藏或键盘显示完成时,我们调整底部约束。

override func viewDidLoad() {
    super.viewDidLoad()
    
    initKeyboardNotifications()
}

//
// https://stackoverflow.com/a/41808338/72437
//
func initKeyboardNotifications() {
    // If your app targets iOS 9.0 and later or macOS 10.11 and later, you do not need to unregister an observer
    // that you created with this function.
    
    NotificationCenter.default.addObserver(self,
        selector: #selector(keyboardWillShow),
        name: UIResponder.keyboardWillShowNotification,
        object: nil)
    NotificationCenter.default.addObserver(self,
        selector: #selector(keyboardWillHide),
        name: UIResponder.keyboardWillHideNotification,
        object: nil)
}

@objc private func keyboardWillShow(sender: NSNotification) {
    let i = sender.userInfo!
    let s: TimeInterval = (i[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
    let k = (i[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
    bottomLayoutConstraint.constant = -k
    
    UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}

@objc private func keyboardWillHide(sender: NSNotification) {
    let info = sender.userInfo!
    let s: TimeInterval = (info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
    bottomLayoutConstraint.constant = 0
    UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}

到目前为止,这是我们不完美的结果。

我想,当键盘被拖动时,我需要实时调整底部约束。但是,我不知道从哪里可以得到键盘高度信息,当它被拖动时。

您知道如何在拖动键盘时实时调整底部约束吗?

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    您可以尝试添加观察者以获取更多通知以观察键盘高度变化。

    UIResponder.keyboardDidChangeFrameNotification

    然后您将获得当前的键盘高度,并可以相应地调整您的布局。


    更新

    keyboardWillChangeFrameNotificationkeyboardDidChangeFrameNotification 在“下拉”期间都不会收到通知。

    您可以尝试将inputAccessoryView 添加到您的文本字段中,这可以帮助您观察键盘框架的变化。

    import UIKit
    
    class FrameObservingInputAccessoryView: UIView {
        var onFrameChange: ((_ frame: CGRect) -> Void)?
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.commonSetUp()
        }
    
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            self.commonSetUp()
        }
        
        private var frameObservation: NSKeyValueObservation?
        override func willMove(toSuperview newSuperview: UIView?) {
            frameObservation?.invalidate()
            frameObservation = newSuperview?.observe(\.frame, changeHandler: { [weak self] (_, _) in
                guard let self = self, let superview = self.superview else { return }
                self.onFrameChange?(superview.frame)
            })
            super.willMove(toSuperview: newSuperview)
        }
        
        deinit {
            frameObservation?.invalidate()
        }
        
        private func commonSetUp() {
            self.isUserInteractionEnabled = false
        }
    }
    

    用法

    class MyCollectionViewCell: UICollectionViewCell, UITextFieldDelegate {
        var onShouldBeginEditing: ((_ textField: UITextField) -> Void)?
        
        func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
            onShouldBeginEditing?(textField)
            return true
        }
    }
    
    class ViewController: UIViewController, UICollectionViewDataSource {
        lazy var frameObservingView: FrameObservingInputAccessoryView = {
            let frameObservingView = FrameObservingInputAccessoryView(frame: .zero)
            frameObservingView.onFrameChange = { [weak self] (frame) in
                // update your constraint
            }
            return frameObservingView
        }()
        
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            5
        }
        
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionViewCell", for: indexPath) as! MyCollectionViewCell
            cell.onShouldBeginEditing = { [weak self] (textField) in
                textField.inputAccessoryView = self?.frameObservingView
            }
            return cell
        }
    }
    

    【讨论】:

    • keyboardWillChangeFrameNotificationkeyboardDidChangeFrameNotification 在“下拉”期间都不会收到通知。
    • @CheokYanCheng 查看更新
    【解决方案2】:

    当键盘显示/隐藏时,您应该调整collectionViewcontentInset.bottom,而不是更改bottomConstraint:

    @objc private func keyboardWillShow(sender: NSNotification) {
        let i = sender.userInfo!
        let s: TimeInterval = (i[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
        let k = (i[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
        collectionView.contentInset.bottom = k
        UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
    }
    
    @objc private func keyboardWillHide(sender: NSNotification) {
        let info = sender.userInfo!
        let s: TimeInterval = (info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
        collectionView.contentInset.bottom = 0
        UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      相关资源
      最近更新 更多