objective-c - 在发生自调整大小之前,如何准确地为 UICollectionViewLayout 提供矩形中的元素?

标签 objective-c uicollectionview autolayout uicollectionviewlayout

我正在使用 UICollectionView 构建可以在网格或垂直列表布局中显示元素的 UI。 UICollectionViewFlowLayout 不能很好地适应全角列表布局,因此我正在编写自己的 UICollectionViewLayout 子类。并且行是自动调整大小的,因此它们可以具有多行标签,并将其字体大小与系统字体大小设置相匹配,并根据需要增大/缩小

在内部,它具有所有行的布局属性的集合。在 prepareLayout(Swift 中的 prepare)中,我遍历数据源中的所有索引路径,并创建布局属性,并将其框架设置为估计行高。

shouldInvalidateLayoutForPreferredLayoutAttributes 中,如果高度与集合中该行的值不同,我将返回 YES。然后,在 invalidationContextForPreferredLayoutAttributes 中,我使传入的 preferredAttributes 的索引路径之后的所有项目无效,因为该行的高度更改会影响所有后续行的垂直位置。然后再次调用 prepareLayout 并根据需要更新所有内容的框架。

问题是由这一系列事件引起的:

  • layoutAttributesForElementsInRect 被调用。我遍历所有属性并检查是否 CGRectIntersectsRect(attr.frame, rect)
  • 对于即将出现的每一行都会调用
  • shouldInvalidateLayoutForPreferredLayoutAttributes 。其中一些最终比最初估计的高度要小。

如果总行收缩足够,则不在 layoutAttributesForElementsInRect 的矩形内的一两行会向上移动到足够的位置,以便它们应该出现。例如,如果矩形的 y 值是 0 到 1334,则在调用 shouldInvalidateLayoutForPreferredLayoutAttributes 之前 y 原点为 1340 的行现在可能位于 1300。但是布局对象已经“知道”应该包含哪些行在屏幕上,所以这些行不会显示,并且我的列表中存在漏洞。

我也许可以通过从 layoutAttributesForElementsInRect 返回额外的行来解决这个问题(通过将我得到的矩形垂直扩展 100 点或其他)。但这是一种黑客行为,API 应该有办法解决这个问题。但在完成自调整大小后,我没有再次调用 layoutAttributesForElementsInRect,并且我没有找到一种方法来要求通过 UICollectionViewLayoutInvalidationContext 再次调用它。

那么...我是否遗漏了 API 中明显的东西?这是一个不应该发生的问题吗?这意味着我正在处理错误的事情吗?在自调整大小发生之前似乎没有办法准确回答 layoutAttributesForElementsInRect...?

说明问题的示例代码是 here在 GitHub 上。

最佳答案

我发现,当您具有自调整大小的补充 View 时,在 invalidationContextForPreferredLayoutAttributes 中进行额外的失效会导致出现布局间隙的错误。我犯了同样的错误,其他人也犯了同样的错误,因为使下面的项目无效并且项目自行调整大小似乎是合乎逻辑的。我的猜测是 Collection View 会为您处理这个问题。

这些are the lines要在示例项目中删除:

[result invalidateItemsAtIndexPaths:rowPaths];
[result invalidateSupplementaryElementsOfKind:UICollectionElementKindSectionHeader atIndexPaths:headerPaths];

我已向 Apple 提交了有关此问题的文档更新 Radar。 http://www.openradar.me/35833995

关于objective-c - 在发生自调整大小之前,如何准确地为 UICollectionViewLayout 提供矩形中的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51389649/

相关文章:

objective-c - 接受UIButtons和UIViews作为方法的参数

iphone - iOS 7 模态显示在状态栏下方

swift - 使用 AlamoFireImage 在 CollectionView 中使用 .af_setImage 方法加载数组的 url 时发生 fatal error

swift - 将 UIViewController 添加到 UICollectionViewCell

iOS 7 - Autolayout - 如何在旋转时更改 View 的位置

mysql - NSPredicate SUBQUERY 用于一对多关系

ios - 在 iOS 应用中打开 iCloud Drive

swift - 如何重置 UICollectionVIewCell 的背景颜色

iOS Autolayout如何水平拉伸(stretch)2个按钮

iOS:使用 AutoLayout 调整 UIImageView 的大小