如何通知 UICollectionView 框架更改

Posted

技术标签:

【中文标题】如何通知 UICollectionView 框架更改【英文标题】:How to be notified of UICollectionView frame changes 【发布时间】:2014-07-20 20:14:30 【问题描述】:

问题: 当我的UICollectionView 的框架发生变化时如何通知我,以便我可以在发生这种情况时运行一些代码?但是,我想知道这是否是解决问题的最佳方法。

问题: 我创建了自己的UICollectionViewLayout,它需要在布置单元格之前知道集合视图的框架大小。问题是,当我将其collectionViewLayout 属性设置为viewDidLoad 中的自定义布局时,集合视图还没有出现在屏幕上。因此,当布局代码运行时,它为 collectionView.frame.size 获得的值是 Interface Builder 中定义的宽度和高度,当集合视图出现在屏幕上时,由于 Autolayout 约束,它会发生变化。这会导致自定义布局在函数collectionViewContentSize 中返回不正确的大小。

目前的解决方案: 为了解决这个问题,我直到viewDidAppear 才更改collectionViewLayout。这确实会导致获得正确的大小。但是,直到使用默认 Flow 布局显示集合视图之后才会这样做,因此所有单元格都已以不同的布局呈现,然后我更改了布局并导致单元格重新呈现。虽然这几乎没有引起注意,因为它发生得如此之快,但显然不是一个好的解决方案。

更好的问题:UICollectionView 帧的大小发生变化时是否可以得到通知?如果是这样,也许我可以在发生这种情况时设置布局,这应该很快就会发生,以防止显示具有默认 Flow 布局的单元格。

如果这不可能,一个看似糟糕但稍微好一点的解决方案可能是在viewDidAppear 中设置新布局之前不显示任何单元格。这将阻止 Flow 布局呈现,但会在短时间内显示空白 UI。

另一种选择是将CGSize 传递给布局类,而不仅仅是访问collectionView.frame.size,这样做我仍然可以在viewDidLoad 中设置自定义布局并防止在流布局中显示单元格。这需要通过某种方式了解集合视图的大小,然后再将其呈现在屏幕上,这可能是不可能的(或至少不准确)。

解决这个问题的最佳方法是什么?

请注意,我无需担心未来的集合视图大小更改,因为布局将失效并在边界更改时重新渲染。

【问题讨论】:

你试过在viewDidLayoutSubviews做吗? viewDidLayoutSubviews被调用了4次,第一次调用frame是Interface Builder中设置的大小,第二次是0 x 0,第三次和第四次调用的值都是正确的。也许没关系,我可以将这些值与 IB 中的值进行比较,并且只在适当的时候设置布局。我会尝试,但也许有更好的解决方案。 @SylvainGuillopé 随意添加这个作为答案,如果我在viewDidLayoutSubviews 中实现大小比较,它对我来说效果很好。 【参考方案1】:

您可以尝试改用 viewDidLayoutSubviews,因为它在 viewDidAppear: 之前被调用,这样您就有机会获得正确的帧值。

文档中的注释:

但是,调用此方法并不表示 视图的子视图的个别布局已调整。

【讨论】:

以上是关于如何通知 UICollectionView 框架更改的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UICollectionView 的大小更改为屏幕大小的一个因素?

如何告诉 UICollectionView 预加载更大范围的单元格?

如何在按钮触摸时更改 UICollectionView 框架

滚动 UICollectionView 以响应键盘通知

获取 UICollectionView 部分的框架

如何将我的 UICollectionView Flowlayout 更改为具有水平滚动的垂直列表