我正在使用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。
答案 0 :(得分:2)
我发现,当您具有自动调整大小的补充视图时,在invalidationContextForPreferredLayoutAttributes
中包含额外的无效项将导致一个错误,使您在布局上出现空白。我犯了同样的错误,其他人也犯了同样的错误,因为使下面的项目无效且项目自调整大小似乎是合乎逻辑的。我的猜测是集合视图可以为您解决这个问题。
要在示例项目中删除的这些are the lines:
[result invalidateItemsAtIndexPaths:rowPaths];
[result invalidateSupplementaryElementsOfKind:UICollectionElementKindSectionHeader atIndexPaths:headerPaths];
我已就此向Apple提交了文档更新Radar。 http://www.openradar.me/35833995
答案 1 :(得分:0)
我的问题是我从自定义布局返回的布局属性缺少 zIndex
属性,因此自动调整大小无法正常工作。