Получение динамической высоты для UICollectionViewCell с пользовательским макетом

#ios #collectionview

#iOS #collectionview

Вопрос:

Мне нужно создать UICollectionView с переменной высотой ячейки, но с сохранением фиксированного вертикального промежутка между ячейками. Что-то вроде этого

Я нашел множество примеров, руководств и библиотек, но для всего этого необходимо реализовать метод делегирования, обеспечивающий высоту для каждого элемента. В моих ячейках есть несколько меток, которые могут содержать одну или несколько строк, поэтому я не знаю заранее конечную высоту элемента после того, как ячейка разместит свои представления.

Есть ли какой-либо способ достичь того, что мне нужно?

Ответ №1:

Вы можете рассчитать высоту своей ячейки с помощью systemLayoutSizeFitting функции.

https://developer.apple.com/documentation/uikit/uiview/1622623-systemlayoutsizefitting

Например: ( UICollectionViewCell является подклассом UICollectionReusableView , поэтому вы также можете использовать это для ячейки и верхнего / нижнего колонтитула)

 public extension UICollectionReusableView {
    static func autoResizingView<T: UICollectionReusableView>(type: T.Type) -> T {
        let nibViews = Bundle.main.loadNibNamed(T.identifier, owner: nil, options: nil)
        return nibViews?.first as? T ?? T()
    }

    static func autoLayoutSize<T: UICollectionReusableView>(type: T.Type, targetWidth: CGFloat, configure: ((T) -> Void)?) -> CGSize {
        let resizingView = UICollectionReusableView.autoResizingView(type: type)
        resizingView.prepareForReuse()
        configure?(resizingView)
        resizingView.setNeedsLayout()
        resizingView.layoutIfNeeded()

        let targetSize = CGSize(width: targetWidth, height: 0)
        let calculateView: UIView
        if let contentView = (resizingView as? UICollectionViewCell)?.contentView {
            calculateView = contentView
        } else {
            calculateView = resizingView
        }
        // Calculate the size (height) using Auto Layout
        let autoLayoutSize = calculateView.systemLayoutSizeFitting(
            targetSize,
            withHorizontalFittingPriority: .required,
            verticalFittingPriority: .defaultLow)
        return autoLayoutSize
    }
}