Как исправить содержимое содержимого uicollectionviewflowlayout, имеющего ячейки с саморазмерным размером? - PullRequest
0 голосов
/ 25 апреля 2019

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

Проблема в том, что правый раздел Inset больше, чем я ожидал - неизвестный разрыв добавлен в правый раздел Inset.

Я реализовал следующие методы.

  1. extendedLayoutAttributesFitting (_ :) пользовательского класса ячейки
    • Рассчитать новый размер ячейки элементов с данными в нем.
  2. estimatedItemSize
    • Я обнаружил, что при использовании метода предпочитаемый_платеж ~ требуется оценка_имя_объекта, иначе происходит сбой.
  3. shouldInvalidateLayout (forPreferredLayoutAttributes ~)
    • Возвращает true, пока все элементы недействительны.
  4. invalidationContext (forPreferredLayoutAttributes ~)
    • В этом методе я добавил предпочтительные атрибуты в локальный массив, чтобы использовать их для последующего вычисления sectionInset.
  5. подготовить ()
    • Расчетный раздел 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
    }
}
...