如何在自动调整大小之前为UICollectionViewLayout的rect中准确提供元素?

时间:2018-07-17 20:23:53

标签: uicollectionview autolayout uicollectionviewlayout

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

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

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

问题与以下事件序列有关:

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

如果行的总收缩量足够大,则layoutAttributesForElementsInRect不在矩形内的一两行将向上移动,足以显示出来。例如,如果rect是y值从0到1334,则在调用shouldInvalidateLayoutForPreferredLayoutAttributes之前,行y始于1340的行现在可以在1300。但是布局对象已经“知道”应该在屏幕上显示哪些行,因此这些行不会显示,并且我的列表中有孔。

我也许可以通过从layoutAttributesForElementsInRect返回多余的行来解决此问题(通过将rect垂直扩展100点之类的东西)。但这是黑客,这似乎是API应该解决的问题。但是,在完成自调整大小后,我没有再接到layoutAttributesForElementsInRect的另一个呼叫,并且我也看不到有一种方法要求通过UICollectionViewLayoutInvalidationContext重新调用它。

那么...我在API中缺少明显的东西吗?这是不应该发生的问题,这意味着我正在处理错误的信息?似乎在自动调整大小之前无法准确回答layoutAttributesForElementsInRect ...?

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

2 个答案:

答案 0 :(得分:2)

我发现,当您具有自动调整大小的补充视图时,在invalidationContextForPreferredLayoutAttributes中包含额外的无效项将导致一个错误,使您在布局上出现空白。我犯了同样的错误,其他人也犯了同样的错误,因为使下面的项目无效且项目自调整大小似乎是合乎逻辑的。我的猜测是集合视图可以为您解决这个问题。

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

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

我已就此向Apple提交了文档更新Radar。 http://www.openradar.me/35833995

答案 1 :(得分:0)

我的问题是我从自定义布局返回的布局属性缺少 zIndex 属性,因此自动调整大小无法正常工作。