使用UICollectionViewLayout的失效上下文

mat*_*son 28 cocoa-touch ios uicollectionview uicollectionviewlayout

因此,我已通过返回实现部分工作在我UICollectionView粘头YESshouldInvalidateLayoutForBoundsChange:.但是,这会影响性能,我不想让整个布局无效,只有我的标题部分无效.

现在,根据我可以用来UICollectionViewLayoutInvalidationContext为我的布局定义自定义失效上下文的官方文档,但文档非常缺乏.它要求我"定义代表可以独立重新计算的布局数据部分的自定义属性",但我不明白它们的含义.

有没有人有任何经验子类UICollectionViewLayoutInvalidationContext

小智 32

这适用于iOS8

我进行了一些实验,我认为我找到了使用失效布局的简洁方法,至少在Apple扩展了文档之前.

我试图解决的问题是在集合视图中获取粘性标头.我使用FlowLayout的子类并覆盖layoutAttributesForElementsInRect来为此工作代码:(您可以在google上找到工作示例).这要求我总是从shouldInvalidateLayoutForBoundsChange返回true:这是Apple希望我们通过上下文无效避免的那些事情中的假设主要性能提升.

清洁上下文无效

您只需要子类化UICollectionViewFlowLayout.我不需要UICollectionViewLayoutInvalidationContext的子类,但这可能是一个非常简单的用例.

当集合视图滚动时,流布局将开始接收shouldInvalidateLayoutForBoundsChange:calls.由于流布局已经可以处理这个问题,我们将在函数末尾返回超类的答案.通过简单的滚动,这将是错误的,并且不会重新布局元素.但是我们需要重新布局标题并让它们保持在屏幕的顶部,因此我们将告诉集合视图仅使我们将提供的上下文无效:

override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
    invalidateLayoutWithContext(invalidationContextForBoundsChange(newBounds))
    return super.shouldInvalidateLayoutForBoundsChange(newBounds)
}
Run Code Online (Sandbox Code Playgroud)

这意味着我们还需要覆盖invalidationContextForBoundsChange:函数.由于此函数的内部工作原理未知,我们只需要向超类询问失效上下文对象,确定我们想要使哪些集合视图元素无效,并将这些元素添加到失效上下文中.我把一些代码拿出来专注于这里的要点:

override func invalidationContextForBoundsChange(newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext! {

    var context = super.invalidationContextForBoundsChange(newBounds)

    if /... we find a header in newBounds that needs to be invalidated .../ {

            context.invalidateSupplementaryElementsOfKind(UICollectionElementKindSectionHeader, atIndexPaths:[NSIndexPath(forItem: 0, inSection:headerIndexPath.section)] )
    }
    return context
}
Run Code Online (Sandbox Code Playgroud)

而已.标题和标题之外的任何内容都无效.流布局将只接受对layoutAttributesForSupplementaryViewOfKind的一次调用:在失效上下文中使用indexPath.如果需要使单元格或装饰器无效,则UICollectionViewLayoutInvalidationContext上还有其他无效*函数.

最难的部分是确定invalidationContextForBoundsChange:函数中头文件的indexPaths.我的两个头和细胞是动态调整大小,它采取了一些杂技得到它从只盯着边界的CGRect工作,因为最明显的有用的功能,indexPathForItemAtPoint:,如果该点位于页眉,页脚,装饰或返回任何内容行间距.

至于性能,我没有进行全面测量,但是在滚动时快速浏览Time Profiler会显示它正在做正确的事情(右边的较小尖峰是在滚动时). UICollectionViewLayoutInvalidationContext性能比较


Pee*_*eks 7

我今天刚刚问了同样的问题,并且也对这个部分感到困惑:"定义代表可以独立重新计算的布局数据部分的自定义属性"

我做的是子类UICollectionViewLayoutInvalidationContext(让我们称之为CustomInvalidationContext)并添加我自己的属性.出于测试目的,我想找出我可以从上下文配置和检索这些属性的位置,因此我只是添加一个数组作为名为"attributes"的属性.

然后在我的子类中,UICollectionViewLayout我覆盖+invalidationContextClass返回一个实例,CustomInvalidationContext在我覆盖的另一个方法中返回的是: -invalidationContextForBoundsChange.在此方法中,您需要调用super,它返回CustomInvalidationContext的实例,然后您可以配置属性并返回.我将属性数组设置为具有对象@["a","b","c"];

然后在另一个覆盖的方法中检索它 - invalidateLayoutWithContext:.我能够从传入的上下文中检索我设置的属性.

因此,您可以设置的属性稍后将允许您计算要提供的索引路径-layoutAttributesForElementsInRect:.

希望能帮助到你.