Как я могу добавить дополнительные дополнительные представления к UICollectionViewFlowLayout с помощью Swift?
Как описано в Руководстве по программированию Представления Коллекции для iOS, если вы хотите добавить новые дополнительные представления или представления художественного оформления к своему Flow Layout, вы должны создать подкласс UICollectionViewFlowLayout.
Мне нужна помощь для реализации следующих шагов в Swift 3:
Стандартный класс макета потока поддерживает только верхний колонтитул раздела и нижний колонтитул раздела, а не виды оформления. Для поддержки дополнительных дополнительных и декоративных видов необходимо как минимум переопределить следующие методы:
- layoutAttributesForElementsInRect: (обязательно)
- layoutAttributesForItemAtIndexPath: (обязательно)
- layoutAttributesForSupplementaryViewOfKind: atIndexPath: (для поддержки новых дополнительных представлений)
- layoutAttributesForDecorationViewOfKind: atIndexPath: (для поддержки новых видов оформления)
В вашем layoutAttributesForElementsInRect: метод вы можете вызвать super, чтобы получить атрибуты макета для ячеек, а затем добавить атрибуты для любых новых дополнительных или декоративных представлений, которые находятся в указанном прямоугольнике. Используйте другие методы для предоставления атрибутов по запросу.
Цели, которых я хотел бы достичь:
- Один дополнительный вид над каждым элементом
- Метод делегата как
referenceSizeForHeaderInSection
определить размер нового дополнительного представления внутри контроллера представления коллекции (return CGSize.zero
если не должно быть "заголовка элемента") - Точный расчетный размер контента
- Вставка, обновление и удаление анимации дополнительного вида с каждым элементом
Обновить
Я знаю, что этот вопрос слишком широко определен. Но с помощью Девона и некоторых собственных идей я нашел решение, которое работает для меня.
Подкласс UICollectionViewFlowLayout
class SBCollectionViewFlowLayout: UICollectionViewFlowLayout { … }
Override
layoutAttributesForElements(in rect: CGRect)
добавить дополнительный дополнительный вид в каждую ячейку.// Check if there already valid layout attributes guard var layoutAttributes = super.layoutAttributesForElements(in: rect) else { return nil } // Try to append new supplementary view to each cell // ──────────────────────────────────────────────────────────── for attributes in layoutAttributes where attributes.representedElementCategory == .cell { if let supplementaryAttributes = layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindDateSeparator, at: attributes.indexPath) { layoutAttributes.append(supplementaryAttributes) } } return layoutAttributes
Override
layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath)
рассчитать положение нового дополнительного вида в представлении коллекции.switch elementKind { case UICollectionElementKindDateSeparator: // Return if there is no collection view or delegate guard let delegate = self.collectionView?.delegate as? SBCollectionViewDelegateFlowLayout else { return nil } // Get the dynamic size of from the delegate let size = delegate.collectionView!(self.collectionView!, layout: self, referenceSizeForSeparatorAt: indexPath) // Return if there the size is (0, 0) if size == CGSize.zero { return nil } // Create new layout attributes for the separator // ════════════════════════════════════════════════════════════ let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: indexPath) if let itemAttributes = layoutAttributesForItem(at: indexPath) { // Position supplementary view at top left edge of the cell // ──────────────────────────────────────────────────────────── attributes.frame = CGRect(x: itemAttributes.frame.origin.x, y: itemAttributes.frame.origin.y, width: size.width, height: size.height) // Increase the item’s position on the z axis // to be sure that the item appear on top of the cell. attributes.zIndex = 1 } return attributes default: // If it is not a date separator, return attributes from flow layout return super.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath) }
"Расширьте" UICollectionViewDelegateFlowLayout, чтобы спросить делегата о размере нового заголовка.
public protocol SBCollectionViewDelegateFlowLayout: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForSeparatorAt indexPath: IndexPath) -> CGSize }
TL; DR
Идея состоит в том, чтобы вместо вставки дополнительных дополнительных видов в представление коллекции, а затем для пересчета всех элементов, я добавляю дополнительный вид сверху соответствующей ячейки. Важно добавить динамический верхний отступ в ячейку, чтобы дополнительный вид не перекрывал какой-либо контент внутри ячейки.
Я надеюсь, что это помогает другим с подобной проблемой!