Я использовал автоматическую компоновку для динамического расчета размера ячейки collectionView. Некоторые ячейки используют размеры из повторно используемых ячеек, когда они впервые прокручиваются для просмотра порта. По мере того как я продолжаю прокручивать collectionView, они будут установлены на правильное значение.
В моем sizeForItemAt
у меня есть следующее:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if let cachedSize = cachedHeightForIndexPath[indexPath] {
return cachedSize
}
if let cell = collectionView.cellForItem(at: indexPath) {
cell.setNeedsLayout()
cell.layoutIfNeeded()
let size = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
cachedHeightForIndexPath[indexPath] = size
print("value is \(size) for indexpath: \(indexPath)")
return size
}
return CGSize(width: ScreenSize.width, height: 0.0)
}
У меня есть три сеанса, в первом разделе высота всей ячейки теоретически равна 88, а во всех остальных разделах высота всей ячейки равна 104.
Изначально виден только первый раздел. Из консоли я вижу, что высота ячейки установлена на 88,0, как и ожидалось. Когда я прокручиваю до оставшихся разделов (первый раздел будет невидимым, а ячейки будут использоваться повторно), некоторые ячейки из второго и третьего разделов используют значение 88,0 в качестве высоты ячеек при первой прокрутке для просмотра порта вместо 104. , По мере того, как я продолжаю прокручивать, ячейка неправильного размера будет использовать 104 в качестве размера. Как заставить все ячейки пересчитывать высоту и не использовать высоту из старой ячейки.
У вас есть правильная идея, но когда вы измеряете ячейку по ее внутренним ограничениям, вызывая systemLayoutSizeFitting
, вместо вызова systemLayoutSizeFitting
для ячейки существующий (collectionView.cellForItem
), вам нужно вооружиться ячейкой модель, которую вы настраиваете так же, как cellForItem
настроил бы его и измерьте это.
Вот как я это делаю (удивительно похоже на то, что у вас есть, с одним отличием; кроме того, я сохраняю размер в модели):
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let memosize = self.sections[indexPath.section].itemData[indexPath.row].size
if memosize != .zero {
return memosize
}
self.configure(self.modelCell, forIndexPath:indexPath) // in common with cellForItem
var sz = self.modelCell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
sz.width = ceil(sz.width); sz.height = ceil(sz.height)
self.sections[indexPath.section].itemData[indexPath.row].size = sz // memoize
return sz
}
Невозможно получить правильное измерение для повторно используемой ячейки даже после заполнения всех данных?
Как узнать, что данные уже заполнены? Вы не должны делать никаких предположений о том, что когдаsizeForItem
будет вызываться для любой конкретной ячейки/элемента. Предположения, которые вы уже делаете, являются причиной ваших проблем! Я говорю вам, как перестать их делать.
Чтобы создать ячейку модели, вам нужно дублировать всю логику настройки представления, например, то, что находится в реальной ячейке, чтобы правильно ее настроить? Как будто это представление, но его нельзя использовать повторно.
Понятно, но как бы вы инициализировали modelCell, поскольку ячейка модели не является фактической ячейкой?