带有自定义 UICollectionViewLayout 的 UICollectionView 中的部分标题

Posted

技术标签:

【中文标题】带有自定义 UICollectionViewLayout 的 UICollectionView 中的部分标题【英文标题】:Header of section in UICollectionView with custom UICollectionViewLayout 【发布时间】:2014-10-21 11:15:19 【问题描述】:

我正在使用自定义布局处理 UICollectionView。两天后我无法理解如何将标题添加到UICollectionView。我有一个非常简单的视图控制器(在故事板中使用自定义布局创建):

class ACollectionViewController: UICollectionViewController 

    enum Identifiers: String 
        case CellIdentifier = "Cell"
        case HeaderIdentifier = "Header"
    

    override func viewDidLoad() 
        super.viewDidLoad()
        self.collectionView.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: Identifiers.HeaderIdentifier.rawValue)
    

    // MARK: UICollectionViewDataSource
    override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int 
        return 1
    

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 10
    

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.CellIdentifier.rawValue, forIndexPath: indexPath) as Cell
        cell.backgroundColor = UIColor.redColor()
        return cell
    

    override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView 
        println("ip = \(indexPath.item)")
        var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView
        supplementaryView.backgroundColor = UIColor.blueColor()
        return supplementaryView
    

这是我的自定义布局:

class ALayout: UICollectionViewLayout 

    override func prepareLayout() 
        super.prepareLayout()
    

    override func collectionViewContentSize() -> CGSize 
        return self.collectionView!.bounds.size
    

    let itemWidth = 40
    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! 
        var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)

        let x: Float = Float(10) * Float(indexPath.item)
        let y: Float = Float(indexPath.item * itemWidth)
        attributes.frame = CGRect(x: CGFloat(x), y: CGFloat(y), width: CGFloat(itemWidth), height: CGFloat(itemWidth))

        return attributes
    

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? 
        var attributes = [UICollectionViewLayoutAttributes]()

        let sectionsCount = self.collectionView!.dataSource!.numberOfSectionsInCollectionView!(self.collectionView!)
        for section in 0..<sectionsCount 
            /// add header
            attributes.append(self.layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, atIndexPath: NSIndexPath(forItem: 0, inSection: section)))

            let itemsCount = self.collectionView!.numberOfItemsInSection(section)
            for item in 0..<itemsCount 
                let indexPath = NSIndexPath(forItem: item, inSection: section)
                attributes.append(self.layoutAttributesForItemAtIndexPath(indexPath))
            
        

        return attributes
    

    override func layoutAttributesForSupplementaryViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! 
        var attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, withIndexPath: indexPath)
        attributes.frame = CGRect(x: 0, y: 0, width: 320, height: 50)

        return attributes
    

问题是我不明白如何正确添加节标题,这个标题的 indexPath 应该是什么。代码中有添加标头的注释。应用程序在启动时崩溃并出现错误

2014-10-21 13:06:22.793 UICollectionViewLayout-Demo[3805:95924] *** Terminating app due to 
uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of 
kind: UICollectionElementKindCell with identifier Header - must register a nib or a class for 
the identifier or connect a prototype cell in a storyboard'

我明白,这是因为单元格的 indexPath 与我要添加的部分标题相同,但标题的 indexPath 应该是什么?还是我做错了?

提前谢谢你。

【问题讨论】:

【参考方案1】:

你的崩溃是因为你正在使用

var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView

尝试使页眉和页脚出列(在collectionView:viewForSupplementaryElementOfKind 中)。改成

var supplementaryView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier:Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView

应该摆脱崩溃,所以你可以调查 indexPath。但在我的测试中,indexPath 始终只是“0”。

【讨论】:

【参考方案2】:

您为标题使用了错误的函数。根据苹果文档,页眉和页脚使用以下内容:

func dequeueReusableSupplementaryViewOfKind(_ elementKind: String,
                        withReuseIdentifier identifier: String,
                               forIndexPath indexPath: NSIndexPath!) -> AnyObject

代替:

 var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView

【讨论】:

【参考方案3】:

而不是

var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView       

应该是

let supplementaryView = collectionView.dequeueReusableSupplementaryViewOfKind(kind withReuseIdentifier:Identifiers.HeaderIdentifier.rawValue, forIndexPath:indexPath)

【讨论】:

以上是关于带有自定义 UICollectionViewLayout 的 UICollectionView 中的部分标题的主要内容,如果未能解决你的问题,请参考以下文章

带有自定义按钮的自定义 UIAlertView

带有自定义数据的自定义 UIActivity

自定义 Combobox 控件自定义数据源,带有自定义 displaymember 和 valuemember

带有自定义后退导航按钮的自定义按钮栏

带有 xib 文件和自定义构造函数的自定义 UITableViewCell

带有自定义 slug 的 wordpress 自定义帖子类型并获取变量