Я работаю над реализацией горизонтального пользовательского UICollectionViewFlowLayout, какая из первой / последней ячейки должна находиться в середине представления и имеет ячейки с саморазмером.
Проблема в том, что правый раздел Inset больше, чем я ожидал - неизвестный разрыв добавлен в правый раздел Inset.
Я реализовал следующие методы.
- extendedLayoutAttributesFitting (_ :) пользовательского класса ячейки
- Рассчитать новый размер ячейки элементов с данными в нем.
- estimatedItemSize
- Я обнаружил, что при использовании метода предпочитаемый_платеж ~ требуется оценка_имя_объекта, иначе происходит сбой.
- shouldInvalidateLayout (forPreferredLayoutAttributes ~)
- Возвращает true, пока все элементы недействительны.
- invalidationContext (forPreferredLayoutAttributes ~)
- В этом методе я добавил предпочтительные атрибуты в локальный массив, чтобы использовать их для последующего вычисления sectionInset.
- подготовить ()
- Расчетный раздел Inset после начального вызова.
- Левая вставка: вычесть ширину первого элемента из ширины collectionView и разделить на две части.
- Правая вставка: вычесть ширину последнего элемента из ширины collectionView и разделить на две части.
Я полагаю, что проблема может быть вызвана оцененным параметром ItemSize, но без него происходит сбой ..
final class CustomCell: UICollectionViewCell {
...
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
let optimalSize = systemLayoutSizeFitting(UIView.layoutFittingExpandedSize)
var newFrame = layoutAttributes.frame
newFrame.size.width = optimalSize.width + 10
layoutAttributes.frame = newFrame
return layoutAttributes
}
...
}
class CustomCollectionViewLayout: UICollectionViewFlowLayout {
override func prepare() {
guard isInitialSetupDone else {
scrollDirection = .horizontal
estimatedItemSize = CGSize(width: 30, height: 40)
minimumInteritemSpacing = 23.3
isInitialSetupDone = true
return
}
// Set sectionInset after invalidation of all items
guard
cache.count == numberOfItems,
let firstItem = cache.first,
let lastItem = cache.last else { return }
let contentSize = collectionViewContentSize
let leftInset : CGFloat = (width - firstItem.frame.width) / 2
let rightInset : CGFloat = (width - lastItem.frame.width) / 2
sectionInset = UIEdgeInsets(top: 3.6, left: leftInset, bottom: 3.6, right: rightInset)
cache.removeAll(keepingCapacity: true)
}
override func shouldInvalidateLayout(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes,
withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> Bool {
let hasOnlyOneItem = (numberOfItems == 1)
let allItemsInvalidated = (cache.count == numberOfItems)
if hasOnlyOneItem {
return true
} else if allItemsInvalidated {
return false
} else {
return true
}
}
override func invalidationContext(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes,
withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutInvalidationContext {
let context = super.invalidationContext(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes)
cache.append(preferredAttributes)
return context
}
}