ios - 如何开发一个自定义的 UICollectionViewLayout,它具有带有自动调整单元格的交错列?

标签 ios swift

我正在开发我已经在 Android 上开发的应用的 iOS 版本。此应用程序具有以下 2 列自调整大小(固定宽度但可变高度)单元格的网格:

Staggered 2 column layout on Android

在 Android 版本中实现这一点很容易,因为 Google 为其 RecyclerView 提供了一个 StaggeredGridLayoutManager。您指定列数和滚动方向即可。

默认的 UICollectionView 布局 UICollectionViewFlowLayout 不允许我正在寻找的交错布局,因此我必须实现自定义布局。我看过 2 个讨论这个主题的 WWDC 视频(What's New in Table and Collection ViewsAdvanced User Interfaces with Collection Views),我或多或少知道应该如何实现。

第 1 步。首先计算布局的近似值。

enter image description here

第 2 步。然后创建单元格并使用自动布局调整大小。

enter image description here

第 3 步。然后 Controller 通知单元格大小,以便更新布局。

enter image description here

在尝试对这些步骤进行编码时,我产生了疑虑。我找到了一个 tutorial这解释了创建具有交错列的自定义布局,但它不使用自动布局来获取单元格的大小。这给我留下了以下问题:

在第2步中,如何以及何时可以获取单元格大小?

在第3步中,如何以及何时通知布局更改?

最佳答案

我想指出,正如您所提到的,RayWenderlich PinInterest Layout正是帮助您实现此布局的教程。

回答您的问题 - 关于教程:

在第2步中,如何以及何时可以获取单元格大小?

为了获取单元格高度,在自定义 UICollectionViewLayoutprepareLayout 方法中调用了一个委托(delegate)方法。此方法被调用一次(或两次,我只是尝试使用print 语句运行它,我得到了两次调用)。 prepareLayout 的要点是初始化单元格的 frame 属性,换句话说,提供每个单元格的确切大小。我们知道宽度是不变的,只有height是变化的,所以在prepareLayout的这一行中:

let cellHeight = delegate.collectionView(collectionView!,
      heightForItemAtIndexPath: indexPath, withWidth: width)

我们从 UICollectionViewController 中实现的委托(delegate)方法获取单元格的高度。对于我们要在 collectionView 中显示的所有单元格,都会发生这种情况。在获取并修改每个单元格的高度后,我们缓存结果以便稍后检查。

之后,collectionView 要获取屏幕上每个单元格的大小,它需要做的就是查询缓存中的信息。这是在自定义 UICollectionViewLayout 类的 layoutAttributesForElementsInRect 方法中完成的。

此方法由 UICollectionViewController 自动调用。当 UICollectionViewController 需要出现在屏幕上的单元格的布局信息时(例如,由于滚动或首次加载),您从填充的缓存中返回属性准备布局

关于您的问题的结论:在第 2 步中,我如何以及何时可以获得像元大小?

回答:每个单元格大小都是在您的自定义 UICollectionViewFlowLayoutprepareLayout 方法中获得的,并且在您的单元格生命周期的早期计算UICollectionView

在第3步中,如何以及何时通知布局更改?

请注意,本教程不考虑在运行时添加的新单元格:

Note: As prepareLayout() is called whenever the collection view’s layout is invalidated, there are many situations in a typical implementation where you might need to recalculate attributes here. For example, the bounds of the UICollectionView might change – such as when the orientation changes – or items may be added or removed from the collection. These cases are out of scope for this tutorial, but it’s important to be aware of them in a non-trivial implementation.

正如他所写,这是一个您可能需要的重要实现。但是,如果您的数据集很小(或出于测试目的),您可能会采用一个简单(非常低效)的实现。当由于屏幕旋转或添加/删除单元格而需要使布局无效时,您可以清除自定义 UICollectionViewFlowLayout 中的缓存以强制 prepareLayout 重新初始化布局属性。

例如,当您必须在 collectionView 上调用 reloadData 时,还要调用您的自定义布局类,以删除缓存:

cache.removeAll()

关于ios - 如何开发一个自定义的 UICollectionViewLayout,它具有带有自动调整单元格的交错列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32398232/

相关文章:

ios - 使用iphone默认提示音

ios - 在应用程序购买中,以编程方式禁用自动更新

swift - 秒表 - 停止和开始

swift - 如何在 UITableView 中移动行后更新 CoreData?

ios - 如何从 cellForItemAtIndexPath 设置 UICollectionViewCell 高度?

ios - 错误:无法推断出通用参数“元素”

sql - 在swift中通过命令行重建SQL数据库

ios - 页面 Controller 中的 ScrollView

javascript - 从 UIWebView 添加 javascript 到页面中

iOS 模拟器 (iPhone6) viewControllers 不匹配 storyBoard Controller