Создание подклассов UICollectionViewFlowLayout - проблема с автоматическим изменением размеров ячейки в iOS 12 - PullRequest
0 голосов
/ 17 сентября 2018

Я использую следующее для выравнивания ячеек по левому краю в UICollectionView

class LeftAlignedFlowLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil }

        for attributes in attributes where attributes.representedElementCategory == .cell {
            attributes.frame = layoutAttributesForItem(at: attributes.indexPath).frame
        }
        return attributes
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes {
        let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)!

        let layoutWidth = collectionView!.frame.width - sectionInset.left - sectionInset.right

        // Just left align the first item in a section
        if indexPath.item == 0 {
            currentItemAttributes.frame.origin.x = sectionInset.left
            return currentItemAttributes
        }

        let previousIndexPath = IndexPath(item: indexPath.item - 1, section: indexPath.section)
        let previousItemFrame = layoutAttributesForItem(at: previousIndexPath).frame

        let currentItemFrame = currentItemAttributes.frame
        let wholeRowFrameForCurrentItem = CGRect(x: sectionInset.left, y: currentItemFrame.minY, width: layoutWidth, height: currentItemFrame.height)

        // Left align the first item on a row
        if !previousItemFrame.intersects(wholeRowFrameForCurrentItem) {
            currentItemAttributes.frame.origin.x = sectionInset.left
            return currentItemAttributes
        }

        currentItemAttributes.frame.origin.x = previousItemFrame.maxX + minimumInteritemSpacing
        return currentItemAttributes, it's 
    }
}

Сборка для iOS 11 дает…

enter image description here

Но для iOS 12 выдает…

enter image description here

В iOS 11 layoutAttributesForElements(in) вызывается 3 раза - в последний раз с правильнымразмеры рамы.В iOS 12 он вызывается только два раза, при этом размер кадра равен предполагаемому размеру.

В соответствии с этим ответом https://stackoverflow.com/a/52148520/123632 Я пытался аннулировать макет потока, используя подкласс UICollectionView ниже (и "перебор "в viewDidAppear содержащего контроллера представления), но результат остается неизменным.

class LeftAlignedCollectionView: UICollectionView {

    private var shouldInvalidateLayout = false

    override func layoutSubviews() {
        super.layoutSubviews()
        if shouldInvalidateLayout {
            collectionViewLayout.invalidateLayout()
            shouldInvalidateLayout = false
        }
    }

    override func reloadData() {
        shouldInvalidateLayout = true
        super.reloadData()
    }
}

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Я нашел решение. Ограничение contentView на ячейку исправило это…

override func awakeFromNib() {
    contentView.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([contentView.leftAnchor.constraint(equalTo: leftAnchor),
                                 contentView.rightAnchor.constraint(equalTo: rightAnchor),
                                 contentView.topAnchor.constraint(equalTo: topAnchor),
                                 contentView.bottomAnchor.constraint(equalTo: bottomAnchor)])
}
0 голосов
/ 14 ноября 2018

Я добавил это в файл MyCustomCollectionViewCell, и он работал нормально

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {

    return contentView.systemLayoutSizeFitting(CGSize(width: targetSize.width, height: 1))
}
0 голосов
/ 18 сентября 2018

Это известная проблема в iOS 12 (см. Раздел UIKit здесь: https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes)

Обходной путь - избегать вызова setNeedsUpdateConstraints() или updateConstraintsIfNeeded() перед вызовом systemLayoutSizeFitting(_:).

...