父类:NSObject
UICollectionViewLayout是抽象基类,你可以使用它的子类来生成对collection view
的布局信息。布局(layout
)对象的工作是决定在collection view
的边界内如何放置cell
、supplementary view
以及decoration view
,并且当collection view
想要获取这些布局信息时能够报告给collection view
。collection view
会根据提供的布局信息来显示对应的视图(view
),以便将视图展现在屏幕上。
一、概述
你必须创建UICollectionViewLayout类的子类才能使用它。在你考虑要创建UICollectionViewLayout类的子类之前,你应该先查看UICollectionViewFlowLayout,看看这个是否符合你的布局需要。
1. 子类提示
布局对象的主要工作是提供collection view
中每一个Item的位置和视觉状态信息。布局对象不会根据他自己提供的布局信息来创建视图。这些视图会被collection view
的数据源来创建。相反,布局对象根据布局的设计定义基础元素的位置和视觉大小。
collection view
有三种需要被设置的视觉元素:
-
Cells——被布局放置的主要元素。每一个cell代表了
collection view
中的一项数据。一个collection view
可以有一组cell,并且它还可以将这些cell分在不同的section中。布局对象的主要工作是在collection view
的内容区域排列这些cell。 -
Supplementary views——也可以显示数据,但是和cell有区别。与cell不同,Supplementary view不可以被用户选择。反而你可以使用Supplementary view来填充section或者整个
collection view
的的头部视图(header view
)和尾部视图(footer view
)。Supplementary view是可选的,并且它们的也是通过布局对象来使用和放置。 -
Decoration views——是在
collection view
不可以被选择的也不可以绑定数据的只能够看的装饰。Decoration view可以说是其他类型的Supplementary view。和Supplementary view一样,Decoration view是可选的,并且也是通过布局对象来使用和放置。
collection view
要求它的布局对象在许多不同的时间为这些元素提供布局信息。每一个cell和视图都使用布局对象提供的安置信息显示在屏幕上。类似的,每次元素从collection view
中插入或删除都会产生额外的布局。collection view
总会将布局限制在屏幕上显示的对象上。
2. 重写的方法
每一个布局对象都应该实现下面的方法:
@property(nonatomic, readonly) CGSize collectionViewContentSize;
- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
-
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
(如果你的布局支持Supplementary view。) -
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
(如果你的布局支持Decoration view。) - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
这些方法提供了collection view
需要在屏幕上放置内容的基本布局信息。当然,如果你的布局不支持Supplementary view或者Decoration view,就不需要重写对应的方法。
当collection view
中的数据改变或者collection view
的Item被插入或删除的时候,collection view
会告知它的布局来更新布局信息。具体的来说,任何一个Item被移动、添加或者删除,它的布局信息都必须更新以反映他的最新位置。对于已经移动的Item来说,collection view
会使用标准方法来重载Item的更新布局属性。对于将要插入或删除的Item来说,collection view
调用一些不同的方法,这些方法你需要重写来提供适当的布局信息:
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;
除了这些方法,你也可以重写- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
方法做与任何一个布局有关的准备。你也可以重写- (void)finalizeCollectionViewUpdates;
方法并用它来添加动画或者处理任何最终布局相关的任务。
3. 使用无效上下文优化布局性能
当你开始设计的自定义布局的时候,你可以使用你布局中确实改变的已经变为无效的部分来提高你的布局的性能。当你改变了一些Item,调用invalidateLayout
方法强制使collection view
重新计算所有布局信息并展示它。一个更好的解决办法是只计算改变部分的布局信息。一个无效上下文会告诉你那个部分的布局改变了。布局对象可以使用这些信息来减少需要计算的数据量。
想要自定义一个你布局中的无效上下文请使用UICollectionViewLayoutInvalidationContext的子类。在你的子类中定义自定义属性,这个属性是你布局数据中可以被独立重新计算的部分。当你想要在运行时中使你的布局无效,创建一个你的无效上下文子类的实例,基于改变的布局信息配置自定义属性,然后把这个实例传入到你的布局的- (void)invalidateLayoutWithContext:(UICollectionViewLayoutInvalidationContext *)context;
方法中。你的自定义实例对于这个方法可以实现使用无效上下文的信息只计算你的布局改变的部分。
如果你为你的布局对象自定义了一个无效内容子类,你也需要重写@property(class, nonatomic, readonly) Class invalidationContextClass;
方法并且返回你的自定义类。collection view
总会在它需要一个无效上下文时创建一个你指定的类。在这个方法中运行你的自定义子类,来确保你的布局对象总有它期望的无效上下文。
二、内容
1. 获取collection view信息
@property (nullable, nonatomic, readonly) UICollectionView *collectionView;
当前正在使用这个布局对象的collection view
对象。
当一个新的布局对象被分配给一个collection view
对象时,这个collection view
对象会设置这个布局对象的这个属性。
@property(nonatomic, readonly) CGSize collectionViewContentSize;
返回collection view
的内容部分的宽度和高度。
子类不许重写这个方法,并且使用它来返回collection view
的内容部分的宽度和高度。这个值表示所有内容的宽度和高度,不仅仅是当前可见内容的高度。collection view
使用这个信息来配置他自己的可以滚动的内容部分的大小。
这个方法的默认实现将会返回CGSizeZero
。
2. 提供布局属性
@property(class, nonatomic, readonly) Class layoutAttributesClass;
返回用来创建布局属性对象的类。
如果你的UICollectionViewLayoutAttributes的子类为了管理额外的布局属性,你需要重写这个方法并返回他自己的自定义子类。当创建新的布局属性对象时这个方法使用这个类创建布局属性。
这个方法只会用到这个子类,而不会调用你的代码。
- (void)prepareLayout;
告诉布局对象来更新当前布局。
布局第一次更新collection view
展示的内容,以及无论何时布局因为视图的改变而失效时。在每次布局更新过程中,collection view
都会首先调用这个方法来让你的布局对象有机会对即将到来的布局操作做准备。
这个方法的默认实现不做任何事情。子类可以重写这个方法用来设置数据结构或执行任何在之后布局中需要的初始计算。
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
返回所有cell和视图在指定范围内的布局属性。
子类必须重写这个方法,并且使用这个方法返回给定范围与视图相交部分的所有Item的布局信息。你的实现需要返回所有可见元素,包括cell、Supplementary view和Decoration view的属性。
当创建布局属性,总会创建一个代表了合适的元素类型(cell、Supplementary view或者Decoration view)的属性对象。collection view
区分每个类型的属性的不同,并且使用这些信息来决定要创建哪些视图以及如何管理它们。
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
返回给定索引值指定的Item的布局属性。
子类必须重写这个方法,并且使用这个方法返回collection view
中的Item的布局信息。你使用这个方法只提供响应的cell的布局信息。这个方法不支持Supplementary view和Decoration view。
- (UICollectionViewLayoutAttributes *)layoutAttributesForInteractivelyMovingItemAtIndexPath:(NSIndexPath *)indexPath withTargetPosition:(CGPoint)position;
返回用户交互时移动的Item的布局属性。
当一个Item因为用户交互而移动时,这个布局对象使用这个方法获得这个Item在指定位置的布局属性。这个方法的默认实现返回这个Item的当前属性的有两个改动的副本:center
点被设置为当前位置的值,zIndex
值被设置为NSIntegerMax
,并使这个Item漂浮在collection view
中的其他Item的上方。
子类可以重写这个方法修改额外需要的布局属性。如果你重写这个方法,首先调用super
获取Item的当前属性,然后返回值做你的更改。
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
返回给定的Supplementary View的布局属性。
如果你的布局对象定义来任何的Supplementary View,你必须重写这个方法,并且使用这个方法返回这些视图的布局信息。
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
返回给定的Decoration View
的布局属性。
如果你的布局对象定义来任何的Decoration View
,你必须重写这个方法,并且使用这个方法返回这些视图的布局信息。
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset;
返回动画布局更新或改变后使用的content offset
。
布局更新过程中,或者在两个布局的过渡过程中,collection view
会调用这个方法让你有机会改变动画结束时建议的content offset
。如果动画或者过度可能导致Item被放置的方法不符合你的设计要求,那么你可以重写这个方法。
collection view
会在调用- (void)prepareLayout;
以及@property(nonatomic, readonly) CGSize collectionViewContentSize;
之后调用这个方法。
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;
- proposedContentOffset CGPoint - 停止滚动的建议位置点(在
collection view
的内容区域中)。这个值如果没有调整将是自然停止的点。这个点指的是可见区域的左上角的点的坐标。 - velocity CGPoint - 沿着水平或垂直滚动的当前速度。这个值表示的是每秒滚动的点的数量。
返回滑动结束的点。
如果你想要滑动行为对齐到指定的边线,你可以重写这个方法,并且使用这个方法改变将要停止的位置点。例如,你可以使用这个方法让滑动停止在两个Item之间的分界线上,而不是停止在一个Item的中间。
3. 响应Collection View更新
- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
通知布局对象,Collection View
的内容将要更新。
当Item被插入或删除时,Collection View
会通知它的布局对象,以便它可以根据需要调整布局。过程的第一步事调用这个方法使布局对象知道预计的改变。之后,继续调用收集整个Collection View
中将要将要有插入,删除和移动动画的Item的布局信息。
- (void)finalizeCollectionViewUpdates;
Collection View
更新期间执行任何额外动画或者清理所需。
Collection View
调用这个方法作为之前动画在当前位置改变的最后一步。这个方法在动画的block里面被调用,用来执行所有插入,删除和移动动画,所以你可以使用这个方法创建需要的额外动画。或者,你可以使用它来执行任何与管理你的布局对象的状态信息相关的最后一分钟任务。
- (NSArray<NSIndexPath *> *)indexPathsToInsertForSupplementaryViewOfKind:(NSString *)elementKind;
- elementKind NSString - 给定Supplementary View的类型。
返回你想要添加到布局中的Supplementary View对应的索引组成的数组。如果你不想添加任何Supplementary View,请返回空数组。
无论你添加cell还是section到Collection View
中,Collection View
都会调用这个方法。实现这个方法让你的布局对象有机会添加新的Supplementary View。
Collection View
在调用- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
和- (void)finalizeCollectionViewUpdates;
方法之间调用这个方法。
- (NSArray<NSIndexPath *> *)indexPathsToInsertForDecorationViewOfKind:(NSString *)elementKind;
- elementKind NSString - 给定Decoration View的类型。
返回你想要添加的Decoration View对应的索引组成的数组。如果你不想添加任何Decoration View,请返回空数组。
无论你添加cell还是section到Collection View
中,Collection View
都会调用这个方法。实现这个方法让你的布局对象有机会添加新的Decoration View。
Collection View
在调用- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
和- (void)finalizeCollectionViewUpdates;
方法之间调用这个方法。
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
返回一个Item插入到Collection View
中开始的布局信息。
这个方法在- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
方法后调用,在- (void)finalizeCollectionViewUpdates;
方法之前调用,在任何一个Item被插入之前都会调用。
你的实现需要返回描述了Item的最初位置和状态的布局信息。Collection View
使用这个信息作为动画的开始位置。(动画的终点位置是这个Item在Collection View
中的新位置。)如果你返回nil
,那么Item会使用它最后的属性作为动画的开始和结束位置。
这个方法的默认实现就是返回nil
。
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;
返回一个Supplementary View插入到Collection View
中开始的布局信息。
这个方法在- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
方法后调用,在- (void)finalizeCollectionViewUpdates;
方法之前调用,在任何一个Supplementary View被插入之前都会调用。
你的实现需要返回描述了Supplementary View的最初位置和状态的布局信息。Collection View
使用这个信息作为动画的开始位置。(动画的终点位置是这个Supplementary View在Collection View
中的新位置。)如果你返回nil
,那么Supplementary View会使用它最后的属性作为动画的开始和结束位置。
这个方法的默认实现就是返回nil
。
.
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;
返回一个Decoration View插入到Collection View
中开始的布局信息。
这个方法在- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
方法后调用,在- (void)finalizeCollectionViewUpdates;
方法之前调用,在任何一个Decoration View被插入之前都会调用。
你的实现需要返回描述了Decoration View的最初位置和状态的布局信息。Collection View
使用这个信息作为动画的开始位置。(动画的终点位置是这个Decoration View在Collection View
中的新位置。)如果你返回nil
,那么Decoration View会使用它最后的属性作为动画的开始和结束位置。
这个方法的默认实现就是返回nil
。
- (NSArray<NSIndexPath *> *)indexPathsToDeleteForSupplementaryViewOfKind:(NSString *)elementKind;
返回将要移除的Supplementary View对应的索引组成的数组。如果你不想移除任何给定的类型的Supplementary View,请返回空数组。
无论你删除Collection View中
的cell还是section,Collection View
都会调用这个方法。实现这个方法让你的布局对象有机会删除不再需要的Supplementary View。
Collection View
在调用- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
和- (void)finalizeCollectionViewUpdates;
方法之间调用这个方法。
- (NSArray<NSIndexPath *> *)indexPathsToDeleteForDecorationViewOfKind:(NSString *)elementKind;
返回将要移除的Decoration View对应的索引组成的数组。如果你不想移除任何给定的类型的Decoration View,请返回空数组。
无论你删除Collection View中
的cell还是section,Collection View
都会调用这个方法。实现这个方法让你的布局对象有机会删除不再需要的Decoration View。
Collection View
在调用- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
和- (void)finalizeCollectionViewUpdates;
方法之间调用这个方法。
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
返回一个Item从Collection View中被移除时的结束布局信息。
这个方法在- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
方法后调用,在- (void)finalizeCollectionViewUpdates;
方法之前调用,在任何一个Item被删除之前都会调用。
Collection View
使用这个信息作为动画的结束位置。(动画的起始位置是这个Item在Collection View
中的当前位置。)如果你返回nil
,那么Item会使用它最后的属性作为动画的开始和结束位置。
这个方法的默认实现就是返回nil
。
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;
返回一个Supplementary View从Collection View中被移除时的结束布局信息。
这个方法在- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
方法后调用,在- (void)finalizeCollectionViewUpdates;
方法之前调用,在任何一个Supplementary View被删除之前都会调用。
Collection View
使用这个信息作为动画的结束位置。(动画的起始位置是这个Supplementary View在Collection View
中的当前位置。)如果你返回nil
,那么Supplementary View会使用它最后的属性作为动画的开始和结束位置。
这个方法的默认实现就是返回nil
。
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;
返回一个Decoration View从Collection View中被移除时的结束布局信息。
这个方法在- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
方法后调用,在- (void)finalizeCollectionViewUpdates;
方法之前调用,在任何一个Decoration View被删除之前都会调用。
Collection View
使用这个信息作为动画的结束位置。(动画的起始位置是这个Decoration View在Collection View
中的当前位置。)如果你返回nil
,那么Decoration View会使用它最后的属性作为动画的开始和结束位置。
这个方法的默认实现就是返回nil
。
- (NSIndexPath *)targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath withPosition:(CGPoint)position;
返回在Collection View
的边界上指定位置的Item的索引值。
在一个Item的交互过程中,这个方法映射了一些在Collection View
的边界上的点对应的索引值。这个方法的默认实现是搜索给定位置存在的cell并返回这个cell的索引值。如果有多个cell在同一个位置,这个方法返回最顶端的cell——即,布局属性的zIndex
属性值最大的cell。
如果需要更改索引值的确定方式,你可以重写这个方法。例如,你可能会返回最小的zIndex
属性值的cell的索引值。如果你重写了这个方法,你不需要调用super
。
4. 无效化布局
- (void)invalidateLayout;
使当前布局无效,并触发一个布局更新。
你可以在任何时间调用这个方法来更新布局信息。这个方法会使Collection View
自己的布局无效,并且立刻返回。因此,你可以在同一个block中多次调用这个方法而不多次触发布局更新。实际上的布局更新发生在下一个视图布局更新周期中。
如果你重写这个方法,你必须在你的实现中的某个点调用super
。
- (void)invalidateLayoutWithContext:(UICollectionViewLayoutInvalidationContext *)context;
-
context
UICollectionViewLayoutInvalidationContext - 标示出了无效化哪一部分的布局。
使用提供的上下文对象无效化当前的布局。
这个方法的默认实现是使用UICollectionViewLayoutInvalidationContext类的基本属性来优化布局过程。如果你给你的布局定义了一个自定义的上下文对象,重写这个方法,并将这个上下文对象的任何自定义属性用于你的布局的计算。
如果你重写这个方法,你必须在你的实现中的某个点调用super
。
@property(class, nonatomic, readonly) Class invalidationContextClass;
返回用于创建布局的无效上下文的类。
如果你子类化UICollectionViewLayout,并且使用一个自定义的无效上下文对象来提高你的布局更新的性能,重写这个方法并返回你的UICollectionViewLayoutInvalidationContext子类。当Collection View
需要无效化你的布局,它会使用你提供的这个类创建一个合适的无效上下文对象。
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
告诉布局对象新的Collection View
的bounds
是否需要布局更新。返回YES
表示Collection View
需要布局更新,返回NO
表示布局不需要更改。
这个方法的默认实现是返回NO
。子类可以重写这个方法,并根据Collection View
的bounds
中是否要求改变cell和Supplementary View的布局来返回一个适当的值。如果Collection View
的bounds
改变并且这个方法返回了YES
,Collection View
就会调用- (void)invalidateLayoutWithContext:(UICollectionViewLayoutInvalidationContext *)context;
方法无效化布局。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForBoundsChange:(CGRect)newBounds;
当bounds
发生改变时返回一个需要变化的定义了部分布局的上下文对象。这个方法不可以返回nil
。
这个方法的默认实现是创建一个invalidationContextClass
提供的类的实例并且返回这个实例。如果你想要使用对你的布局自定义的无效上下文对象,需要重写这个方法返回你的自定义类的实例。
如果你想要在响应bounds
改变时创建并配置你的自定义无效上下文你可以重写这个方法。如果你重写了这个方法,你必须首先调用super
来得到返回的无效上下文对象。得到这个对象之后,设置你想要设置的属性,然后返回这个对象。
- (BOOL)shouldInvalidateLayoutForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes;
- preferredAttributes UICollectionViewLayoutAttributes - cell的
- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes;
方法返回的布局属性。 - originalAttributes UICollectionViewLayoutAttributes - 布局对象对cell的最初建议属性。
一个自动调整大小的cell改变时,询问布局对象是否需要一个较大的更新。当一个Collection View
包含自动调整大小的Cell时,让这些Cell在自己的布局属性生效之前有机会修改这些属性。一个自动调整大小的Cell可能指定一个不同的Cell大小而不是提供的布局对象。当这个Cell提供一个不同的属性集合,Collection View
调用这个方法来确定Cell的改变是否需要较大的布局更新。
如果你实现一个自定义布局,你可以重写这个方法并且用这个方法根据给定的属性来确定是否你的布局需要被无效化。这个方法的默认实现是返回NO
。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes;
当一个动态Cell改变时,返回一个上下文对象来标示出需要改变的部分布局。
这个方法的默认实现是创建一个invalidationContextClass
提供的类的实例,并返回这个实例。如果你想要对你的布局使用一个自定义无效上下文对象,重写这个方法,并返回你的自定义的类的实例。
子类化可以重写这个方法,使用这个方法在返回之前来执行额外的对无效上下文的配置。在你的自定义实现中调用super
,以便父类可以执行对这个对象的基本配置。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForInteractivelyMovingItems:(NSArray<NSIndexPath *> *)targetIndexPaths withTargetPosition:(CGPoint)targetPosition previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths previousPosition:(CGPoint)previousPosition;
- targetIndexPaths NSArray - 正在移动的Item的当前索引值。
- targetPosition CGPoint -
Collection View
坐标系内的点,是Item可能拖动的点。 - previousIndexPaths NSArray - 正在移动的Item的之前的索引值。
- previousPosition CGPoint -
Collection View
坐标系内的点。这个点是之前用来确定Item拖动点的。
返回一个上下文对象,这个对象标示了在布局中被交互移动的Item。
在交互移动一个或多个Item的过程中,布局对象使用这个方法来获取无效上下文。这个方法的默认实现是创建一个invalidationContextClass
提供的类的对象,使用提供的信息填入这个对象,并且返回这个对象。如果你想要对你的布局使用一个自定义无效上下文对象,重写这个方法,并返回你的自定义的类的实例。
子类化可以重写这个方法,使用这个方法在返回之前来执行额外的对无效上下文的配置。在你的自定义实现中调用super
,以便父类可以执行对这个对象的基本配置。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:(NSArray<NSIndexPath *> *)indexPaths previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths movementCancelled:(BOOL)movementCancelled;
-
indexPaths
NSArray - Item的最终索引值。对于取消的交互,这个索引值对应了Item的最初索引值。 -
previousIndexPaths
NSArray - Item之前的索引值。这个参数包含了Collection View
在一系列移动中报告的最后一组索引值。 -
movementCancelled
BOOL - 标示了移动交互是成功结束还是被取消了。
返回一个上下文对象,这个对象标示了被移动的Item。
当交互移动一个或多个Item结束时(移动成功或者被用户取消了移动),布局对象使用这个方法来获取无效上下文。这个方法的默认实现是创建一个invalidationContextClass
提供的类的对象,使用提供的信息填入这个对象,并且返回这个对象。如果你想要对你的布局使用一个自定义无效上下文对象,重写这个方法,并返回你的自定义的类的实例。
子类化可以重写这个方法,使用这个方法在返回之前来执行额外的对无效上下文的配置。在你的自定义实现中调用super
,以便父类可以执行对这个对象的基本配置。
5. Coordinating Animated Changes
- (void)prepareForAnimatedBoundsChange:(CGRect)oldBounds;
为了动态改变视图的bounds
或者Item的插入删除准备布局对象。
Collection View
在执行任何动态改变视图的bounds
或者动态的插入删除Item之前都会调用这个方法。这个方法让布局对象有机会为这些动态改变进行任何需要的计算准备。具体来说,你可能使用这个方法计算插入或删除的Item的最初的和最终的位置,以便当需要这些值的时候你可以返回这些值。
你也可以使用这个方法来处理额外的动画。你创建的任何动画被添加到动画的block中,用来处理插入、删除以及bounds
的改变。
- (void)finalizeAnimatedBoundsChange;
在动态改变视图的bounds
或者Item的插入删除之后进行清理。
Collection View
在创建改变视图的bounds
的动画或者动态插入或删除Item之后调用这个方法。这个方法让布局对象有机会清除和这些操作有关的内容。
你也可以使用这个方法来处理额外的动画。你创建的任何动画被添加到动画的block中,用来处理插入、删除以及bounds
的改变。
6. 两个布局之间的过渡
- (void)prepareForTransitionFromLayout:(UICollectionViewLayout *)oldLayout;
告诉布局对象准备为Collection View
安装布局。
在执行布局转换之前,Collection View
调用这个方法,以便与你的布局对象可以执行一些最初的有需要的计算来生成布局属性。
- (void)prepareForTransitionToLayout:(UICollectionViewLayout *)newLayout;
告诉布局对象,这个正要从Collection View
中被移除的布局。
在执行布局转换之前,Collection View
调用这个方法,以便与你的布局对象可以执行一些最初的有需要的计算来生成布局属性。
- (void)finalizeLayoutTransition;
告诉布局对象在过渡动画发生之前执行任何最终步骤。
当Collection View
已经了解了从一个布局转换到另一个布局所有需要的布局属性后,Collection View
调用这个方法。你可以使用这个方法清除任何数据结构或者清除你在prepareForTransitionFromLayout
或prepareForTransitionToLayout
方法中实现时产生的缓存。
7. 注册Decoration View
- (void)registerClass:(Class)viewClass forDecorationViewOfKind:(NSString *)elementKind;
- viewClass Class - 用来创建Decoration View的类。
- elementKind NSString - Decoration View的类型。你可以使用这个字符串在布局中来区分不同的Decoration View。这个参数不可以传
nil
,也不可以传入一个空的字符串。
注册一个Collection View
用来创建Decoration View的类。
这个方法让布局对象有机会注册一个在Collection View
中使用的Decoration View。Decoration View为整个Collection View
提供可见的装饰,但是和Collection View
的数据源提供的数据没有关系。
你不需要显式的创建Decoration View。注册一个之后,布局对象来决定是否需要一个Decoration View,如果需要则通过layoutAttributesForElementsInRect:
方法返回对应的布局属性。对于给定的Decoration View的布局属性,Collection View
会根据注册的信息来创建(或者重用)一个视图并且自动展示它。
如果你之前使用同样的字符串注册一个类或者nib
文件,你在viewClass
参数中指定的这个类会替换旧的记录。如果你想取消注册Decoration View,你可以对viewClass
指定为nil
。
- (void)registerNib:(UINib *)nib forDecorationViewOfKind:(NSString *)elementKind;
注册一个Collection View
用来创建Decoration View的nib
文件。
这个方法让布局对象有机会注册一个在Collection View
中使用的Decoration View。Decoration View为整个Collection View
提供可见的装饰,但是和Collection View
的数据源提供的数据没有关系。
你不需要显式的创建Decoration View。注册一个之后,布局对象来决定是否需要一个Decoration View,如果需要则通过layoutAttributesForElementsInRect:
方法返回对应的布局属性。对于给定的Decoration View的布局属性,Collection View
会根据注册的信息来创建(或者重用)一个视图并且自动展示它。
如果你之前使用同样的字符串注册一个类或者nib
文件,你在viewClass
参数中指定的这个类会替换旧的记录。如果你想取消注册Decoration View,你可以对viewClass
指定为nil
。