如何在发生自动调整大小之前为UICollectionViewLayout的rect中准确提供元素? [英] How do I accurately provide elements in a rect for UICollectionViewLayout before self-sizing has occurred?

查看:132
本文介绍了如何在发生自动调整大小之前为UICollectionViewLayout的rect中准确提供元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using UICollectionView to build UI that can display elements in a grid or a vertical list layout. UICollectionViewFlowLayout doesn't play well with a full-width list layout, so I'm writing my own UICollectionViewLayout subclass. And the rows are self-sizing, so that they can have multiline labels and match their font size to the system font size setting and grow/shrink as needed

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

Internally, it has a collection of layout attributes for all rows. In prepareLayout I walk over all index paths in the data source and create layout attributes with their frames set for an estimated row height.

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

In shouldInvalidateLayoutForPreferredLayoutAttributes, I return YES if the height is different than the value I have for that row in my collection. Then in invalidationContextForPreferredLayoutAttributes, I invalidate all items after the index path of the passed-in preferredAttributes, because a height change in this row affects the vertical position of all subsequent rows. Then prepareLayout gets called again and I update the frames of everything as necessary.

问题来自以下一系列事件:

The problem comes with this sequence of events:

  • layoutAttributesForElementsInRect被调用.我遍历所有属性并检查是否CGRectIntersectsRect(attr.frame, rect).
  • shouldInvalidateLayoutForPreferredLayoutAttributes对于即将出现的每一行都会被调用.其中一些最终比原来的估计高度小.
  • layoutAttributesForElementsInRect gets called. I walk over all my attributes and check if CGRectIntersectsRect(attr.frame, rect).
  • shouldInvalidateLayoutForPreferredLayoutAttributes gets called for each row that is about to appear. Some of them end up smaller than the estimated height they had originally.

如果行的总收缩量足够大,则layoutAttributesForElementsInRect的区域中不存在的一两行将向上移动,足以显示出来.例如,如果rect是y值0到1334,则在shouldInvalidateLayoutForPreferredLayoutAttributes调用之前的y源为1340的行现在可以在1300.但是布局对象已经知道"应该在屏幕上显示哪些行,因此只是没有显示行,而且我的列表中有孔.

If the total row shrinkage is enough, a row or two that weren't within the rect for layoutAttributesForElementsInRect get moved up enough that they should appear. For example, if the rect was y values 0 through 1334, a row with y origin 1340 before the calls to shouldInvalidateLayoutForPreferredLayoutAttributes could now be at 1300. But the layout object already "knows" what rows are supposed to be onscreen, so those rows just don't show up, and there are holes in my list.

我也许可以通过从layoutAttributesForElementsInRect返回额外的行来解决此问题(通过将rect垂直扩展100点之类的东西).但这是一个hack,这似乎是API应该解决的问题.但是,在自动调整大小之后,我没有再接到layoutAttributesForElementsInRect的另一个呼叫,而且我也看不到要求通过UICollectionViewLayoutInvalidationContext再次调用它的方法.

I might be able to work around this by returning extra rows from layoutAttributesForElementsInRect (by expanding the rect I get by 100 points vertically or something). But that's a hack, and this seems like something that the APIs should have a way to address. But I don't get another call to layoutAttributesForElementsInRect after self-sizing is done, and I don't see a way to ask for it to be called again via UICollectionViewLayoutInvalidationContext.

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

So...am I missing something obvious in the API? Is this a problem that shouldn't be happening, which means I'm approaching something wrong? It seems like there's no way to accurately answer layoutAttributesForElementsInRect before self-sizing has happened...?

说明问题的示例代码是此处在GitHub上.

Example code illustrating the problem is here on GitHub.

推荐答案

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

I've discovered that having extra invalidations in invalidationContextForPreferredLayoutAttributes when you have self-sizing supplementary views will cause a bug where you get layout gaps. I've made the same mistake and others have too because it seems logical to invalidate the items below and item being self-sized. My guess is that the collection view handles this for you.

这些是这些行在示例项目中删除:

These are the lines to remove in your sample project:

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

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

I've filed a documentation update Radar with Apple about this. http://www.openradar.me/35833995

这篇关于如何在发生自动调整大小之前为UICollectionViewLayout的rect中准确提供元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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