invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:) не вызывается для пользовательского подкласса NSCollectionViewLayout

Ссылка на соответствующий пример проекта

Описание

Я пытаюсь создать кастом NSCollectionViewLayout подкласс, который использует Auto Layout для определения размеров своих элементов. Этот макет размещает элементы сверху вниз, где все элементы имеют одинаковую ширину, но высота каждого элемента определяется его содержимым. Думайте об этом как UITableView макет для macOS.

предположение

Начальные атрибуты макета рассчитываются в макете prepare() метод, и передается в коллекцию через layoutAttributesForElements(in:), Эти атрибуты используются представлением коллекции, чтобы определить, какие элементы необходимо отобразить. Эти элементы предоставляются делегатом представления коллекции, а каждый элемент apply(_:) метод вызывается для установки его свойств вида.

Представление коллекции затем вызовет элемент preferredLayoutAttributesFitting(_:) метод для расчета размера его содержимого. Возвращенные атрибуты затем будут переданы в макет представления коллекции. shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:) метод, в котором макет определяет, нужно ли вносить коррективы в ответ на новые атрибуты, и возвращает это логическое решение в представление коллекции.

Если макет решит, что его нужно сделать недействительным, представление коллекции затем вызовет invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:) получить конкретную информацию из макета о том, как она должна обновляться сама. Когда представление коллекции затем вызывает invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)макет может применить эти изменения.

Этот процесс затем повторяется до shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:) возвращается false для каждого элемента макета - запрос представления коллекции для отображения элементов на экране.

посылка

ListLayout подкласс NSCollectionViewLayout в состоянии создать начальный набор атрибутов макета для каждого NSCollectionViewItem с "предполагаемой" начальной высотой 10 точки. Мы ожидаем использовать Auto Layout для определения фактической высоты каждого элемента, поэтому это начальное значение не должно иметь значения.

Затем макет может предоставить правильный набор этих начальных атрибутов через layoutAttributesForElements(in:),

TextFieldItem подкласс NSCollectionViewItem содержит один NSTextField экземпляр, который установлен как его view а также textField свойства. Эта точка зрения имеет свои translatesAutoresizingMaskIntoConstraints свойство имеет значение false и имеет требуемый приоритет сопротивления сжатию вертикального содержимого. Предметы apply(_:) метод переопределяется для установки текстового поля preferredMaxLayoutWidth на ширину, обеспечиваемую данными атрибутами. Предметы preferredLayoutAttributesFitting(_:) метод переопределяется, чтобы установить высоту предпочтительного атрибута равной текстовому полю intrinsicContentSize имущество.

Представление коллекции предоставляется экземпляры TextFieldItem заполнен несколькими строками текста.

Ожидается, что каждый TextFieldItem будет иметь preferredLayoutAttributesFitting(_:) метод вызывается после его apply(_:) метод с последующим вызовом обоих макетов shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:) а также invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:) методы.

Тем не менее, ни preferredLayoutAttributesFitting(_:)ни shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)ни invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:) когда-либо вызваны, когда детская площадка запущена. В результате высота каждого элемента остается на этой начальной "оценочной" высоте.

Каждое текстовое поле должно отображать три строки текста, но видна только верхняя часть первой строки

Вопрос

Должно быть что-то, о чем я скучаю NSCollectionViewLayout и Auto Layout, но я не нашел ничего в документации, чтобы указать на это.

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

Есть ли свойство, которое необходимо установить в представлении коллекции, его макете или элементах, указывающих, что preferredLayoutAttributesFitting(_:) должен называться? Auto Layout поддерживается только для подклассов NSCollectionViewFlowLayout а также NSCollectionViewGridLayout? Или я неправильно понимаю жизненный цикл NSCollectionViewLayout пример?

1 ответ

У меня та же проблема, это мое решение, оно работает отлично. Добавьте приведенный ниже код в подкласс UICollectionViewCell.

override func awakeFromNib() {

    super.awakeFromNib()

    self.contentView.translatesAutoresizingMaskIntoConstraints = false

    let leftConstraint = contentView.leftAnchor.constraint(equalTo: leftAnchor)
    let rightConstraint = contentView.rightAnchor.constraint(equalTo: rightAnchor)
    let topConstraint = contentView.topAnchor.constraint(equalTo: topAnchor)
    let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
    NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint])
}
Другие вопросы по тегам