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])
}