UICollectionViewLayout

UICollectionViewLayout

我的应用程序具有UIViewController类;在此类中,我连接了从情节提要加载的UICollectionView
我正在使用UICollectionViewLayout类创建自定义布局。看起来是这样的:

class MyLayout: UICollectionViewLayout {

    override func prepareLayout() {
        super.prepareLayout()
    }

    override func collectionViewContentSize() -> CGSize {
        let attributes = super.collectionViewContentSize()
        return attributes
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
        let attributes = super.layoutAttributesForElementsInRect(rect) as? [UICollectionViewLayoutAttributes]
        return attributes
    }

    override func layoutAttributesForItemAtIndexPath(indexPath:
    NSIndexPath) -> UICollectionViewLayoutAttributes {
        let attributes = super.layoutAttributesForItemAtIndexPath(indexPath)
        return attributes
    }
}
要将UICollectionViewLayout分配给UICollectionView,我使用collectionViewLayoutUICollectionView属性:
myCollectionView.collectionViewLayout = MyLayout()
运行该应用程序后,UICollectionViewCells不再可见。不过,在分配UICollectionViewLayout之前,它们是可见的。我现在只能看到UICollectionView的背景。
为什么细胞不再可见?
更新
我仔细查看了自己UICollectionViewLayoutAttributesUICollectionView,尤其是contentSize。我打印出它的值,它似乎等于(0.0, 0.0)attributeslayoutAttributesForElementsInRect值也等于nil。绝对是一个红旗。
Download the project

最佳答案

首先,您应该使用布局初始化UICollectionView,而不是事后设置它:

var collectionView = UICollectionView(frame: frame, collectionViewLayout: myLayout)

documentation:

通常,在创建集合视图时指定一个布局对象[...]

接下来,如果您是UICollectionViewLayout的子类,则必须实现collectionViewContentSize并返回您自己的值。在这里,未定义调用super的定义,除非您将UICollectionViewFlowLayout子类化。

子类必须重写此方法,并使用它返回集合视图内容的宽度和高度。这些值表示所有内容的宽度和高度,而不仅仅是当前可见的内容。收集视图使用此信息来配置其自身的内容大小以进行滚动。

这是因为UICollectionViewLayout本身是一个不执行任何操作的抽象类(它应该被子类化)。

UICollectionViewLayout类是抽象基类,您可以将其子类化并用于生成集合视图的布局信息。

同样,您还需要在layoutAttributesForElementsInRect:中计算自己的layoutAttributes。最简单的方法是在prepareLayout方法中计算所需的所有布局,然后再获取所需的布局。这是自定义布局的“核心”:
  • 向委托人询问您必须在collectionView中显示的元素数量。
  • 对于每个元素,首先创建正确的indexPath,然后使用UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)为该indexPath创建一个空的layoutAttribute。
  • 计算并设置该layoutAttribute的frame属性。
  • 将该layoutAttribute存储在声明为MutableArray的 private 属性中。
  • layoutAttributesForElementsInRect:中,遍历先前实例化的所有已存储的layoutAttributes,并返回其子集frame与提供的rect相交的子集。 UICollectionView将要求其dataSource为该方法(通过cellForItemAtIndexPath)返回的每个layoutAttributes提供一个单元格,并将使用这些layoutAttributes中的frame属性设置这些单元格的frame

  • 如果您既可以阅读Swift也可以阅读Objective-C,则可以看看my sample UICollectionViewLayout implementation here,它使UICollectionView模仿iOS日历应用程序的每日视图(screenshot)。

    如果您的目标是实现一个相当标准的布局(即放置在水平或垂直流动的网格中的元素),则建议您从子类化UICollectionViewFlowLayout开始,因为它已经是UICollectionViewLayout的有效实现,这意味着您可以在大多数方法中使用super来获取默认值。

    另外,请阅读here in the official documentation,了解如何创建自己的自定义布局。

    07-24 09:24