UICollectionView становится неправильным поведением FirstResponder

Я использую представление UIColletion с пользовательской ячейкой с UITextField внутри нее. Как я узнал, collectionView выполняет автоматическую прокрутку, когда textField становится первым ответчиком, поэтому клавиатура не закрывает редактируемое поле.

Проблема в том, что эта функция не работает должным образом. Он прокручивает текстовое поле в нужное место прямо над клавиатурой, но затем прокручивает его немного ниже, потому что клавиатура скрывает часть текстового поля.

Я попробовал новый новый проект только с одним простым представлением коллекции только с одной ячейкой прототипа с текстовым полем в нем, и он тоже не работает.

В моем исходном проекте с гораздо более сложной ячейкой вторая прокрутка намного больше, поэтому все текстовое поле находится под клавиатурой.

Это ошибка в представлении коллекции или я что-то не так делаю? (в простом проекте почти не может быть ничего плохого....


person Martin Kubišta    schedule 17.08.2017    source источник
comment
Не могли бы вы добавить немного кода, который вы используете в своем новом небольшом проекте?   -  person Cal Stephens    schedule 17.08.2017
comment
Опубликовано как новый ответ   -  person Martin Kubišta    schedule 18.08.2017
comment
@MartinKubišta Пожалуйста, проверьте ответ ниже. Добавлен фрагмент, который также кажется более универсальным решением.   -  person George Bafaloukas    schedule 18.08.2017
comment
Наличие похожей проблемы. Любые обновления?   -  person jlmurph    schedule 09.11.2017


Ответы (2)


Что касается моего типового проекта.

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

введите здесь описание изображения

person Martin Kubišta    schedule 18.08.2017

только что воссоздал ваш проект и, похоже, хорошо работает для тестирования на iPhone 7 plus.

Представление коллекции прокручивается и показывает текстовое поле. Теперь одна проблема заключается в том, что отступы под клавиатурой не всегда одинаковы. Мое предложение в вашем случае - убедиться, что у вас есть ограничения для вашего текстового поля, и повторить попытку. Это может иметь значение.

С другой стороны, я бы предложил использовать ScrollView вместо представления коллекции. Представления коллекций имеют повторное использование ячеек, что может вызвать у вас проблемы с точки зрения повторного использования ячеек и освобождения текстовых полей.

Что я обычно делаю, когда у меня есть форма с большим количеством текстовых полей, это следующее:

  • Создайте scrollView и закрепите его на всех краях. Особенно важно нижнее ограничение
  • Добавьте представление в scrollView, прикрепите его ко всем краям и сделайте ширину и высоту вашего встроенного UIView равными ширине и высоте суперпредставления ScrollViews. (Таким образом, вставки прокрутки будут масштабироваться правильно)
  • Добавьте свои текстовые поля в качестве подвидов в UIView выше.
  • Добавьте наблюдателей для уведомлений клавиатуры в свой UIViewController и анимируйте нижнее ограничение scrollView до высоты клавиатуры и обратно до 0, когда клавиатура перемещается от экрана.

Таким образом, вы убедитесь, что контролируете анимацию экрана, и вы можете добавить больше отступов, если считаете это необходимым. ScrollView будет обрабатывать сопротивление и размещать текстовое поле в правильном окне просмотра.

Кроме того, вы сможете иметь ссылки на все ваши текстовые поля. Либо создав розетки, либо добавив их в 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()
        })
    }
}

введите здесь описание изображения

person George Bafaloukas    schedule 18.08.2017
comment
Я знаю об этом решении, но его нельзя сделать в нашем проекте. Весь экран представляет собой своего рода форму с множеством различных видов ввода, а текстовое поле является лишь одним из таких вводов. И он не статичен, а полностью сгенерирован кодом вокруг нашего подкласса collectionview, который обрабатывает некоторые изменения макета, основные входные данные, изменение порядка элементов и многое другое... - person Martin Kubišta; 18.08.2017
comment
Тем не менее автономное поведение представления коллекции выглядит для меня ошибкой. Я попробовал это с дополнительным видом, и он ведет себя так же. youtu.be/lN-I59qF2cY - person Martin Kubišta; 18.08.2017