如何使用 swift 在集合视图中同时制作页眉和页脚

问题描述 投票:0回答:10

如何在 swift 中在集合视图中同时制作页眉和页脚?

我试图将页眉和页脚组合在一起,但它一直崩溃,我找不到快速教程来理解它。

我不知道如何返回两者的补充视图,而只是一个。

我将它们都设置在故事板上(类+标识符)

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    //#warning Incomplete method implementation -- Return the number of sections
    return 2
}

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    //#warning Incomplete method implementation -- Return the number of items in the section
    return 10
}

override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    var header: headerCell!
    var footer: footerCell!

    if kind == UICollectionElementKindSectionHeader {
        header =
            collectionView.dequeueReusableSupplementaryViewOfKind(kind,
                withReuseIdentifier: "header", forIndexPath: indexPath)
            as? headerCell
    }
    
    return header
}

错误: 标识符为一的 UICollectionElementKindCell - 必须为标识符注册一个笔尖或一个类,或者连接故事板中的原型单元'

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> profileCC {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("one", forIndexPath: indexPath) as! profileCC

    // Configure the cell

    return cell
}



override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    
    switch kind {
        
    case UICollectionElementKindSectionHeader:
        
        let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "header", forIndexPath: indexPath) as! headerCell
        
        headerView.backgroundColor = UIColor.blueColor();
        return headerView
        
    case UICollectionElementKindSectionFooter:
        let footerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "footer", forIndexPath: indexPath) as! footerCell
        
        footerView.backgroundColor = UIColor.greenColor();
        return footerView
        
    default:
        
        assert(false, "Unexpected element kind")
    }
}

希望有人帮忙。

ios swift uicollectionview
10个回答
103
投票

您可以制作一个

UICollectionViewController
来处理
UICollectionView
,并在Interface Builder中激活FooterHeader部分,然后您可以使用以下方法在您的
UICollectionView
中预览添加的两个部分:

override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    
    switch kind {
        
    case UICollectionView.elementKindSectionHeader:
        
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath)
        
        headerView.backgroundColor = UIColor.blue
        return headerView
        
    case UICollectionView.elementKindSectionFooter:
        let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Footer", for: indexPath)
        
        footerView.backgroundColor = UIColor.green
        return footerView
        
    default:
        
        assert(false, "Unexpected element kind")
    }
}

在上面的代码中,我将页脚和页眉的

identifier
设置为
Header
Footer
,例如,您可以按照自己的意愿进行操作。如果您想创建自定义页眉或页脚,那么您需要为每个页眉或页脚创建一个
UICollectionReusableView
的子类,并根据需要对其进行自定义。

您可以在 Interface Builder 中或在代码中注册自定义页脚和页眉类:

registerClass(myFooterViewClass, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "myFooterView")

91
投票

更新为 Swift 3+

第1步:

在视图控制器类中,注册要用作页眉、页脚或两者的类:

let collectionViewHeaderFooterReuseIdentifier = "MyHeaderFooterClass"

第2步:

如果使用 xib,请使用:

collectionView.register(UINib(nibName: collectionViewHeaderFooterReuseIdentifier bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier:collectionViewHeaderFooterReuseIdentifier)

collectionView.register(UINib(nibName: collectionViewHeaderFooterReuseIdentifier bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier:collectionViewHeaderFooterReuseIdentifier)

如果不使用 xib:

collectionView.register(MyHeaderFooterClass.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier)

collectionView.register(MyHeaderFooterClass.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier)

第三步:

创建自定义页眉/页脚类,实现如下:

import UIKit

class MyHeaderFooterClass: UICollectionReusableView {

 override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.purple

    // Customize here

 }

 required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

 }
}

第 4 步: 如果不使用 xib,请忽略

  • 创建一个新的空 xib:“文件 --> 新文件 --> 空”。

  • 将其命名为与类完全相同的名称。 在此示例中:“MyHeaderFooterClass”

  • 向 xib 添加集合可重用视图。
  • 单击该对象,选择身份检查器并将该对象的类更改为“MyHeaderFooterClass”。

第5步: - 通过委托方法支持集合视图中的新单元格:

 func collectionView(_ collectionView: UICollectionView,
                    viewForSupplementaryElementOfKind kind: String,
                    at indexPath: IndexPath) -> UICollectionReusableView {

    switch kind {

    case UICollectionElementKindSectionHeader:
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier, for: indexPath)

        headerView.backgroundColor = UIColor.blue
        return headerView

    case UICollectionElementKindSectionFooter:
        let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier, for: indexPath)

        footerView.backgroundColor = UIColor.green
        return footerView

    default:
        assert(false, "Unexpected element kind")
    }
}

第6步: 手柄尺寸/使其出现:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: 180.0)
}
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
        return CGSize(width: 60.0, height: 30.0)
}

16
投票

除了上面所有的答案

激活页脚和页眉部分

选择您的集合,然后选择属性检查器并检查页脚和页眉部分

就像照片中的那样

enter image description here


9
投票

为了补充剩余的答案,不要忘记为页眉/页脚视图分配空间,否则

collectionView:viewForSupplementaryElementOfKind:atIndexPath
不会被调用

通过在 collectionView 数据源中实现

collectionView:layout:referenceSizeForHeaderInSection
来实现这一点。


7
投票

Xcode 11+ 和 iOS 13+

我正在使用 Xib 创建页眉和页脚视图

  1. 像这样为页眉和页脚创建 Xib 和类文件(与页脚类相同)并为两者创建 xib 视图
class HeaderViewCV: UICollectionReusableView {

}
  1. 像这样注册 Xib Cells
collectionView.register(UINib(nibName: "HeaderViewCV", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "HeaderViewCV") //elementKindSectionFooter for footerview
  1. 页眉和页脚查看方法
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    
   switch kind {
                
   case UICollectionView.elementKindSectionHeader:
            let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderViewCV", for: indexPath)
            return headerView
            
    case UICollectionView.elementKindSectionFooter:
            let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FooterViewCV", for: indexPath)
            return footerView
            
     default:
            assert(false, "Unexpected element kind")
    }
}
  1. 对于两者的视图高度方法
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    return CGSize(width: self.collectionView.frame.width, height: 55)
}


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
    return CGSize(width: self.collectionView.frame.width, height: 67)
}
  1. 完成 CollectionView 中页眉和页脚的所有必要要求已准备就绪

7
投票

使用@mobilecat代码后,您应该使用此功能使页眉和页脚出现

func collectionView(
    _ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
    referenceSizeForHeaderInSection section: Int
) -> CGSize {
    return CGSize(width: collectionView.frame.width, height: 180.0)
}
func collectionView(
    _ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
    referenceSizeForFooterInSection section: Int
) -> CGSize {
    return CGSize(width: 60.0, height: 30.0)
}

3
投票

解决方案

class CustomFlowLayout: UICollectionViewFlowLayout {

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
        var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()

        for attributes in attributesForElementsInRect! {

            if !(attributes.representedElementKind == UICollectionElementKindSectionHeader
                || attributes.representedElementKind == UICollectionElementKindSectionFooter) {

                // cells will be customise here, but Header and Footer will have layout without changes.
            }

            newAttributesForElementsInRect.append(attributes)
        }

        return newAttributesForElementsInRect
    }
}


class YourViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let headerNib = UINib.init(nibName: "HeaderCell", bundle: nil)
        collectionView.register(headerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderCell")

        let footerNib = UINib.init(nibName: "FooterCell", bundle: nil)
        collectionView.register(footerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "FooterCell")
    }


    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        switch kind {
        case UICollectionElementKindSectionHeader:
            let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderCell", for: indexPath) as! HeaderCell
            return headerView
        case UICollectionElementKindSectionFooter:
            let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FooterCell", for: indexPath) as! FooterCell
            return footerView
        default:
            return UICollectionReusableView()
        }
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: 45)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: 25)
    }
}

3
投票

如果您需要为页眉和页脚保留空白空间,请扩展

UICollectionViewDelegateFlowLayout
并使用此代码相应地设置页眉或页脚。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let footerValue = 150
    let headerValue = 150
    collectionView.contentInset = UIEdgeInsets(top: headerValue, left: 0, bottom: footerValue, right: 0)
}

2
投票

请注意,您的 viewController 必须实现 UICollectionViewDelegateFlowLayout ,否则这些方法将不会被调用

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

}

1
投票

以下@mobilecat详细答案,如果您使用组合集合视图,请在创建布局时添加这些行:

let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44))
let headerElement = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)

并将

headerElement
设置为您的部分,如下所示:

 let section = NSCollectionLayoutSection(group: group)
 section.boundarySupplementaryItems = [headerElement]

完整的代码片段是:

private func createCompositionalLayout() -> UICollectionViewCompositionalLayout {
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalHeight(1.0),
                                          heightDimension: .fractionalHeight(0.2))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)

    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                           heightDimension: .fractionalWidth(1.0))
    
    let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
    
    let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44))
    let headerElement = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)

    let section = NSCollectionLayoutSection(group: group)
    section.boundarySupplementaryItems = [headerElement]


    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
  }
© www.soinside.com 2019 - 2024. All rights reserved.