【问题标题】:UICollectionView becomeFirstResponder wrong behaviorUICollectionView becomeFirstResponder 错误行为
【发布时间】:2017-08-17 15:45:33
【问题描述】:

我正在使用带有自定义单元格的 UIColletion 视图,其中包含 UITextField。我发现,当 textField 成为第一响应者时,collectionView 会自动滚动,因此键盘不会覆盖已编辑的字段。

问题是,这个功能不能正常工作。它将文本字段滚动到键盘上方的正确位置,但接下来它会向下滚动一点,因为键盘隐藏了部分文本字段。

我尝试了一个新项目,只有一个简单的集合视图,其中只有一个带有文本字段的原型单元格,但它也不起作用。

在我的原始项目中,单元格更复杂,第二个滚动条更大,因此整个文本字段都在键盘下方。

这是集合视图中的错误还是我做错了什么? (在简单的项目中几乎不会有任何问题......

【问题讨论】:

  • 您能添加一些您在新的小型项目中使用的代码吗?
  • 发布为新答案
  • @MartinKubišta 请检查下面的答案。添加了一个 sn-p,这似乎也是一个更通用的解决方案
  • 有类似的问题。有更新吗?

标签: ios swift uicollectionview becomefirstresponder


【解决方案1】:

至于我的示例项目。

UICollectionViewController

import UIKit

private let reuseIdentifier = "Cell"

class CollectionCollectionViewController: UICollectionViewController {

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

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */

    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items
        return 50
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? CollectionViewCell

        cell?.field.backgroundColor = .red

        return cell ?? UICollectionViewCell()
    }

}

UICollectionViewCell

import UIKit

class CollectionViewCell: UICollectionViewCell {
    @IBOutlet var field: UITextField!
}

【讨论】:

    【解决方案2】:

    刚刚重新创建了您的项目,似乎对我在 iPhone 7 plus 上进行测试很有效。

    集合视图滚动并显示文本字段。现在的一个问题是键盘下方的填充并不总是相同的。在您的情况下,我的建议是确保您的文本字段的约束到位,然后再试一次。这可能会有所作为。

    另一方面,我建议使用 ScrollView 而不是集合视图。 集合视图具有单元格重用,这可能会给您带来单元格被重用和文本字段被释放方面的问题。

    当表单中有很多 TextFields 时,我通常会做以下事情:

    • 创建一个滚动视图并固定到所有边缘。尤其是底部约束很重要
    • 在 scrollView 中添加视图将其固定到所有边缘,并使封闭 UIView 的宽度和高度等于 ScrollViews 父视图的宽度和高度。 (这样滚动插图将正确缩放)
    • 将您的文本字段作为子视图添加到上面的 UIView 中
    • 在 UIViewController 中为键盘通知添加观察者,并将滚动视图的底部约束设置为键盘高度,并在键盘从屏幕移开一段距离时返回 0。

    这样可以确保您控制屏幕动画,并且如果您觉得有必要可以添加更多填充。 scrollView 将处理抵抗并将您的 textField 放置在正确的视口中。

    此外,您将能够引用所有文本字段。通过创建 outlet 或将它们添加到 OutletCollection。

    我通常这样做是为了让它们保持有序并将焦点移到列表中的下一个。

    import UIKit
    
    class KeyboardViewController: UIViewController {
    
        @IBOutlet weak var bottomScrollViewConstraint: NSLayoutConstraint!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            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)
        }
    
        @IBAction func hideKeyboard(_ sender: Any) {
            self.view.endEditing(true)
        }
    
        func keyboardWillShow(notification: NSNotification) {
    
            if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
                self.bottomScrollViewConstraint.constant = keyboardSize.height //Add more padding here if you want
                UIView.animate(withDuration: 0.8, animations: { 
                    self.view.layoutIfNeeded()
                })
            }
    
        }
    
        func keyboardWillHide(notification: NSNotification) {
            self.bottomScrollViewConstraint.constant = 0
            UIView.animate(withDuration: 0.8, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }
    

    【讨论】:

    • 我知道这个解决方案,但在我们的项目中无法做到。整个屏幕是某种形式,有许多不同类型的输入,文本字段只是这种输入中的一种。它不是静态的,而是完全由我们的 collectionview 子类周围的代码生成的,它处理一些布局更改、基本输入、项目重新排序等等......
    • 对于我来说,集合视图的自主行为仍然看起来像一个错误。我用附件视图试过它,它的行为是一样的。 youtu.be/lN-I59qF2cY
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    相关资源
    最近更新 更多