UICollectionView成为FirstResponder错误的行为

时间:2017-08-17 15:45:33

标签: ios swift uicollectionview becomefirstresponder

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

问题是,此功能无法正常工作。它将文本字段滚动到键盘正上方的右侧,但接下来它会向下滚动一点点,键盘会隐藏文本字段的一部分。

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

在我的原始项目中,单元格更加复杂,第二个卷轴要大得多,所以整个文本区域都在键盘下。

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

2 个答案:

答案 0 :(得分:0)

至于我的示例项目。

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!
}

enter image description here

答案 1 :(得分:0)

刚刚重新创建了你的项目,似乎对我在iPhone 7 plus上的测试很有帮助。

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

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

拥有包含大量TextFields的表单时,我通常会执行以下操作:

  • 创建一个scrollView并固定到所有边缘。特别是底部约束很重要
  • 在scrollView中添加视图将其固定到所有边缘,并使包含的UIView的宽度和高度等于ScrollViews超级视图的宽度和高度。 (这样滚动插图将正确缩放)
  • 将textFields作为Subviews添加到上面的UIView
  • 在UIViewController中添加键盘通知的观察者,并将scrollView的底部约束设置为键盘的高度,并在键盘从屏幕移开时返回0。

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

此外,您将能够引用所有textFields。通过创建出口或将它们添加到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()
        })
    }
}

enter image description here