为什么在将 UICollectionViewLayout 分配给 UICollectionView 后 UICollectionViewCells 不再可见? [英] Why are UICollectionViewCells no longer visibile after assigning a UICollectionViewLayout to the UICollectionView?

查看:21
本文介绍了为什么在将 UICollectionViewLayout 分配给 UICollectionView 后 UICollectionViewCells 不再可见?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用有一个 UIViewController 类;在这个类中,我连接了一个从 Storyboard 加载的 UICollectionView.

My app has a UIViewController class; inside this class I connect a UICollectionView loaded from a Storyboard.

我正在使用 UICollectionViewLayout 类创建自定义布局.这是它的样子:

I'm creating a custom layout with the UICollectionViewLayout class. Here's what it looks like:

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,我使用 UICollectionViewcollectionViewLayout 属性:

To assign a UICollectionViewLayout to the UICollectionView, I use the collectionViewLayout property of the UICollectionView:

myCollectionView.collectionViewLayout = MyLayout()

运行应用程序,UICollectionViewCells 不再可见.不过,它们在分配 UICollectionViewLayout 之前是可见的.我现在只能看到 UICollectionView 的背景.

Running the app, the UICollectionViewCells are no longer visible. Though, they were visible before assigning the UICollectionViewLayout. I can now only see the background of the UICollectionView.

为什么单元格不再可见?

Why are cells no longer visibile?

更新

我仔细查看了我的 UICollectionViewUICollectionViewLayoutAttributes,尤其是 contentSize.我打印了它的值,它似乎等于 (0.0, 0.0).layoutAttributesForElementsInRectattributes 值也等于 nil.绝对是一个危险信号.

I looked carefully at the UICollectionViewLayoutAttributes of my UICollectionView, particularly the contentSize. I printed out its value and it seems to be equal to (0.0, 0.0). The attributes value for layoutAttributesForElementsInRect is also equal to nil. Definitely a red flag.

推荐答案

首先,你应该用你的布局初始化你的 UICollectionView 而不是之后设置它:

First of all, you should be initializing your UICollectionView with your layout instead of setting it afterward:

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

来自文档:

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

You normally specify a layout object when creating a collection view [...]

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

Next, if you subclass UICollectionViewLayout, you must implement collectionViewContentSize and return a value of your own. Calling super is undefined here, unless you are subclassing UICollectionViewFlowLayout.

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

Subclasses must override this method and use it to return the width and height of the collection view’s content. These values represent the width and height of all the content, not just the content that is currently visible. The collection view uses this information to configure its own content size for scrolling purposes.

那是因为 UICollectionViewLayout 本身是一个抽象类,它什么都不做(它意味着被子类化).

That's because UICollectionViewLayout as itself is an abstract class that does nothing (it is meant to be subclassed).

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

The UICollectionViewLayout class is an abstract base class that you subclass and use to generate layout information for a collection view.

同样,您还需要在 layoutAttributesForElementsInRect: 中计算自己的 layoutAttributes.最简单的方法是在 prepareLayout 方法中计算所有您需要的布局,然后获取您需要的布局.这是自定义布局的核心":

In the same way, you also need to compute your own layoutAttributes in layoutAttributesForElementsInRect:. The easiest is to compute all your required layout in the prepareLayout method, and just get the ones you need afterwards. This is the "core" of a custom layout:

  • 向委托人询问您必须在 collectionView 中显示的元素数量.
  • 对于每个元素,首先创建正确的 indexPath,然后使用 UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) 为该 indexPath 创建一个空的 layoutAttribute.
  • 计算并设置该 layoutAttribute 的 frame 属性.
  • 将该 layoutAttribute 存储在声明为 MutableArray 的私有属性中.
  • layoutAttributesForElementsInRect: 中,遍历之前实例化的所有存储的 layoutAttributes,并返回其中 frame 与提供的 rect 相交的子集.UICollectionView 将要求其 dataSource 为该方法返回的每个 layoutAttributes 提供一个单元格(通过 cellForItemAtIndexPath),并且这些单元格的 frame 将使用那些 layoutAttributes 中的 frame 属性进行设置.
  • Ask the delegate for the number of elements you have to display in your collectionView.
  • For each element, first create the right indexPath, then create an empty layoutAttribute for that indexPath with UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath).
  • Compute and set the frame property of that layoutAttribute.
  • Store that layoutAttribute in a private property declared as a MutableArray.
  • In layoutAttributesForElementsInRect:, iterate through all your stored layoutAttributes previously instantiated, and return a subset of those with their frame intersecting the provided rect. The UICollectionView will ask its dataSource to provide a cell for every layoutAttributes returned by that method (via cellForItemAtIndexPath), and the frame of those cells will be set using the frame property in those layoutAttributes.

如果你能读懂 Objective-C 和 Swift,你可以看看 我的示例 UICollectionViewLayout 实现在这里,它使 UICollectionView 模仿 iOS 日历应用程序的每日视图(截图).

If you can read Objective-C as well as Swift, you could take a look at my sample UICollectionViewLayout implementation here, which makes the UICollectionView mimic the daily view of the iOS calendar app (screenshot).

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

If your goal is to achieve a layout that if fairly standard (i.e. elements disposed in a grid that flows horizontally or vertically), I'd recommend you to start by subclassing UICollectionViewFlowLayout instead, as it is already a valid implementation of UICollectionViewLayout, meaning you could use super in most methods to get the default values.

另外,请阅读此处关于如何创建自己的自定义布局的官方文档.

这篇关于为什么在将 UICollectionViewLayout 分配给 UICollectionView 后 UICollectionViewCells 不再可见?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆