#ios #swift #uicollectionview #uicollectionreusableview #uicollectionviewflowlayout
#iOS #swift #uicollectionview #uicollectionreusableview #uicollectionviewflowlayout
Вопрос:
У меня есть UICollectionView
, с включенным верхним и нижним колонтитулами:
Здесь задается высота нижнего колонтитула:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
if isLoading {
return CGSize.zero
}
return CGSize(width: collectionView.bounds.size.width, height: 55)
}
… и я установил здесь как верхний, так и нижний колонтитулы:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionFooter {
let aFooterView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerViewReuseIdentifier, for: indexPath) as! CustomFooterView
self.footerView = aFooterView
self.footerView?.backgroundColor = UIColor.green
return aFooterView
} else {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "HeaderView", for: indexPath) as! CollectionViewHeader
return headerView
}
}
И зарегистрируйте их здесь:
collectionView?.register(CollectionViewHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "HeaderView")
collectionView?.register(UINib(nibName: "CustomFooterView", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: footerViewReuseIdentifier)
Когда я настраиваю представление коллекции на использование макета по умолчанию, я могу видеть как верхний, так и нижний колонтитулы. Когда я устанавливаю для него значение ниже, пользовательский макет, я вижу только заголовок, но НЕ нижний колонтитул, и я не понимаю, почему это так:
class ColumnFlowLayout: UICollectionViewFlowLayout {
private let minColumnWidth: CGFloat = 300.0
private let cellHeight: CGFloat = 184.0
private var deletingIndexPaths = [IndexPath]()
private var insertingIndexPaths = [IndexPath]()
// MARK: Layout Overrides
/// - Tag: ColumnFlowExample
override func prepare() {
super.prepare()
guard let collectionView = collectionView else { return }
let availableWidth = collectionView.bounds.inset(by: collectionView.layoutMargins).width
let maxNumColumns = Int(availableWidth / minColumnWidth)
let cellWidth = (availableWidth / CGFloat(maxNumColumns)).rounded(.down)
self.itemSize = CGSize(width: cellWidth, height: cellHeight)
self.sectionInset = UIEdgeInsets(top: self.minimumInteritemSpacing, left: 0.0, bottom: 0.0, right: 0.0)
self.sectionInsetReference = .fromSafeArea
}
// MARK: Attributes for Updated Items
override func finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let attributes = super.finalLayoutAttributesForDisappearingItem(at: itemIndexPath) else { return nil }
if !deletingIndexPaths.isEmpty {
if deletingIndexPaths.contains(itemIndexPath) {
attributes.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
attributes.alpha = 0.0
attributes.zIndex = 0
}
}
return attributes
}
override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let attributes = super.initialLayoutAttributesForAppearingItem(at: itemIndexPath) else { return nil }
if insertingIndexPaths.contains(itemIndexPath) {
attributes.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
attributes.alpha = 0.0
attributes.zIndex = 0
}
return attributes
}
// MARK: Updates
override func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {
super.prepare(forCollectionViewUpdates: updateItems)
for update in updateItems {
switch update.updateAction {
case .delete:
guard let indexPath = update.indexPathBeforeUpdate else { return }
deletingIndexPaths.append(indexPath)
case .insert:
guard let indexPath = update.indexPathAfterUpdate else { return }
insertingIndexPaths.append(indexPath)
default:
break
}
}
}
override func finalizeCollectionViewUpdates() {
super.finalizeCollectionViewUpdates()
deletingIndexPaths.removeAll()
insertingIndexPaths.removeAll()
}
}
РЕДАКТИРОВАТЬ По какой-то причине, если я установил
collectionView.collectionViewLayout = ColumnFlowLayout()
, нижний колонтитул равен нулю, но если я не установил макет ColumnFlowLayout
, нижний колонтитул будет выделен правильно.
РЕДАКТИРОВАНИЕ 2 может подтвердить, что в этом методе делегирования:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionFooter {
let aFooterView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerViewReuseIdentifier, for: indexPath) as! CustomFooterView
self.footerView = aFooterView
self.footerView?.backgroundColor = UIColor.green
return aFooterView
} else {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "HeaderView", for: indexPath) as! CollectionViewHeader
return headerView
}
}
Когда у меня есть:
collectionView.collectionViewLayout = ColumnFlowLayout()
,
программа никогда не достигает if kind == UICollectionView.elementKindSectionFooter
, но она достигает этого, если collectionView.collectionViewLayout = ColumnFlowLayout()
закомментировано.
Ответ №1:
Понял это; необходимо вручную установить высоту нижнего колонтитула внутри ColumnFlowLayout
реализации следующим образом:
self.footerReferenceSize = CGSize(width: w, height: h)