UICollectionView не отображает нижний колонтитул при использовании пользовательского макета потока

#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)