UICollectionViewLayout的基础知识

UICollectionViewLayout (布局对象)

1、创建集合视图布局的方法:

typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {
    UICollectionViewScrollDirectionVertical,
    UICollectionViewScrollDirectionHorizontal
};
#pragma mark --------创建集合视图布局
//创建集合视图布局对象。
- (instancetype)init;
//从给定unarchiver中的数据创建集合视图布局对象。
- (instancetype)initWithCoder:(NSCoder *)coder;

2、获取集合视图信息的方法:

#pragma mark -------- 获取集合视图信息 
// 当前使用此布局对象的集合视图对象。 
@property(nullable, nonatomic, readonly) UICollectionView *collectionView;
// 集合视图内容的宽度和高度。 
@property(nonatomic, readonly) CGSize collectionViewContentSize;

3、提供布局属性的方法:

#pragma mark ------- 提供布局属性 
//创建布局属性对象时要使用的类.
//用于布局属性对象的类.
//如果你子类化UICollectionViewLayoutAttributes来管理额外的布局属性,
//你应该重写这个方法并返回你的自定义子类。
//创建布局属性的方法在创建新的布局属性对象时使用这个类。
//此方法仅用于子类,不需要由代码调用。
@property(class, nonatomic, readonly) Class layoutAttributesClass;

//告诉布局对象更新当前的布局。
//布局更新发生在集合视图第一次显示其内容时,
//以及布局因视图更改而显式或隐式失效时,都会进行布局更新。
//在每次布局更新期间,集合视图首先调用这个方法,
//使布局对象有机会为即将到来的布局操作做准备。
//此方法的默认实现不执行任何操作。
//子类可以覆盖它,并使用它来设置数据结构或执行以后执行布局所需的任何初始计算。
- (void)prepareLayout;

//检索指定矩形中所有单元格和视图的布局属性。
//UICollectionViewLayoutAttributes对象数组,表示单元格和视图的布局信息。
//默认实现返回nil。
//子类必须重写此方法,并使用它返回视图与指定矩形相交的所有项的布局信息。
//您的实现应该返回所有可视元素的属性,包括单元格、补充视图和装饰视图。
//在创建布局属性时,总是创建一个表示正确元素类型(单元格、补充或装饰)的属性对象。
//集合视图区分每种类型的属性,并使用该信息来决定创建哪些视图以及如何管理它们。
- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

//检索具有相应单元格的指定索引路径上的项的布局信息。
//一个布局属性对象,包含要应用到该项单元格的信息。
//子类必须重写此方法,并使用它返回集合视图中项目的布局信息。
//使用此方法仅为具有相应单元格的项提供布局信息。
//不要将它用于补充视图或装饰视图!!!
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

//当一个item被用户交互式移动时,检索该item的布局属性。
//item 位于指定位置时的布局属性。
//当项由于用户交互而移动时,布局对象使用此方法检索项在指定位置时要使用的布局属性。
//该方法的默认实现返回一个项目现有属性的副本,
//并进行了两个更改:中心点被设置为position中的值,
//zIndex值被设置为NSIntegerMax,以便项目在集合视图中浮动在其他项目之上。
//子类可以覆盖这个方法,并根据需要修改额外的布局属性。
//如果重写此方法,请首先调用super检索该项的现有属性,然后对返回的结构进行更改。
//indexPath 被移动的项目的索引路径。
//position   item 在集合视图坐标系中的当前位置
- (UICollectionViewLayoutAttributes *)layoutAttributesForInteractivelyMovingItemAtIndexPath:(NSIndexPath *)indexPath  
withTargetPosition:(CGPoint)position;

//检索指定补充视图的布局属性。
//一个布局属性对象,包含应用到补充视图的信息。
//如果布局对象定义了任何补充视图,则必须重写此方法并使用它返回这些视图的布局信息。
//elementKind 标识补充视图类型的字符串。
//indexPath  视图的索引路径.
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind
     atIndexPath:(NSIndexPath *)indexPath;

//检索指定装饰视图(Decoration View)的布局属性.
// 布局属性对象,包含要应用于装饰视图的信息。 
//如果布局对象定义了任何装饰视图,则必须重写此方法并使用它来返回这些视图的布局信息。
//elementKind 标识 装饰视图(Decoration View)类型的字符串。
//indexPath  视图的索引路径.
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind 
      atIndexPath:(NSIndexPath *)indexPath;

//检索在动画布局更新或更改后要使用的内容偏移量。
//您要使用的内容偏移量。此方法的默认实现返回proposedContentOffset参数中的值。
//在布局更新期间,或在布局之间转换时,集合视图调用此方法,
//以便您有机会更改要在动画结束时使用的建议内容偏移。
//如果动画或过渡可能导致项目的定位方式不是最适合您的设计,则可以重写此方法。
//集合视图在调用prepareLayout和collectionViewContentSize方法之后调用该方法。
// proposedContentOffset 提议的内容偏移 
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset;

// 检索停止滚动的点。 
//您要使用的内容偏移量。该值反映了调整后的可见区域的左上角。
//此方法的默认实现返回proposedContentOffset参数中的值。
//如果希望滚动行为捕捉到特定的边界,可以重写此方法并使用它来更改停止的点。
//例如,您可以使用此方法始终在项目之间的边界上停止滚动,而不是在项目中间停止滚动。
//proposedContentOffset 建议停止滚动的点(在集合视图的内容视图中)。
//如果不做任何调整,滚动就会自然停止。该点反映可见内容的左上角。
//velocity 当前沿水平轴和垂直轴的滚动速度。该值以每秒点数为单位。
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset 
   withScrollingVelocity:(CGPoint)velocity;

4、响应集合视图更新的方法:

#pragma mark -------  响应集合视图更新 
// 通知布局对象集合视图的内容即将更改。 
//当插入或删除项时,集合视图通知它的布局对象,以便它可以根据需要调整布局。
//这个过程的第一步是调用这个方法,让布局对象知道预期会发生什么变化。
//在此之后,将进行其他调用,以收集插入、删除和移动项的布局信息,这些项将围绕集合视图进行动画化。
- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;

//执行在集合视图更新期间所需的任何其他动画或清理。
//集合视图调用此方法作为将任何更改动画化之前的最后一步.
//此方法在用于执行所有插入、删除和移动动画的动画块中调用,
//因此您可以根据需要使用此方法创建其他动画。
//否则,您可以使用它来执行与管理布局对象的状态信息相关的任何最后一分钟的任务。
- (void)finalizeCollectionViewUpdates;

//检索要添加到布局中的补充视图的索引路径数组。
//NSIndexPath对象数组,表示新的补充视图的位置,
//如果不想添加任何补充视图,则为空数组。
//每当向集合视图添加cells或sections时,集合视图都会调用此方法。
//实现此方法使您的布局对象有机会添加新的补充视图来补充添加的内容。
//集合视图在调用prepareForCollectionViewUpdates:和 
//finalizeCollectionViewUpdates之间调用此方法。
- (NSArray<NSIndexPath *> *)indexPathsToInsertForSupplementaryViewOfKind:(NSString *)elementKind;

//检索表示要添加的装饰视图的索引路径数组。
//NSIndexPath对象数组,表示新装饰视图的位置,
//如果不想添加任何装饰视图,则为空数组。
//每当向集合视图添加cells或sections时,集合视图都会调用此方法。
//实现此方法使布局对象有机会添加新的装饰视图来补充添加的内容。
//集合视图在调用prepareForCollectionViewUpdates:和
//finalizeCollectionViewUpdates之间调用此方法。
- (NSArray<NSIndexPath *> *)indexPathsToInsertForDecorationViewOfKind:(NSString *)elementKind;

//检索插入到集合视图中的项的起始布局信息。
//一个布局属性对象,用于描述要放置相应单元格的位置。
//该方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于即将插入的任何项。
//您的实现应该返回描述该项的初始位置和状态的布局信息。
//集合视图使用这些信息作为任何动画的起点(动画的结束点是项目在集合视图中的新位置)。
//如果你返回nil,布局对象使用项目的final属性作为动画的开始点和结束点。
//此方法的默认实现将返回nil。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;

//检索插入到集合视图中的补充视图的起始布局信息。
//一个布局属性对象,它描述放置相应补充视图的位置。
//该方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于即将插入的任何补充视图。
//您的实现应该返回描述视图初始位置和状态的布局信息。
//集合视图使用这些信息作为任何动画的起点(动画的结束点是视图在集合视图中的新位置)。
//如果你返回nil,布局对象使用项目的final属性作为动画的开始点和结束点。
//此方法的默认实现将返回nil。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind 
          atIndexPath:(NSIndexPath *)elementIndexPath;

//检索插入到集合视图中的装饰视图的起始布局信息。
//一个布局属性对象,描述放置相应装饰视图的位置。
//这个方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于任何即将插入的装饰视图。
//您的实现应该返回描述视图初始位置和状态的布局信息。
//集合视图使用这些信息作为任何动画的起点(动画的结束点是视图在集合视图中的新位置)。
//如果你返回nil,布局对象使用项目的final属性作为动画的开始点和结束点。
//此方法的默认实现将返回nil。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind 

//检索表示要删除的补充视图的索引路径数组。
//NSIndexPath对象数组,表示要删除的补充视图;
//如果不想删除任何给定类型的视图,则为空数组。
//每当向集合视图删除cells或sections时,集合视图都会调用此方法。
//实现此方法使布局对象有机会删除不再需要的任何补充视图。
//集合视图在调用prepareForCollectionViewUpdates:和
//finalizeCollectionViewUpdates之间调用此方法。
- (NSArray<NSIndexPath *> *)indexPathsToDeleteForSupplementaryViewOfKind:(NSString *)elementKind;

//检索表示要删除的装饰视图的索引路径数组。
//NSIndexPath对象数组,表示要删除的装饰视图;
//如果不想删除任何给定类型的视图,则为空数组。
//每当向集合视图删除cells或sections时,集合视图都会调用此方法。
//实现此方法使布局对象有机会删除不再需要的任何装饰视图。
//集合视图在调用prepareForCollectionViewUpdates:和
//finalizeCollectionViewUpdates之间调用此方法。
- (NSArray<NSIndexPath *> *)indexPathsToDeleteForDecorationViewOfKind:(NSString *)elementKind;

//检索即将从集合视图中删除的项的最终布局信息。
//一个布局属性对象,描述要用作动画删除单元格的终点的单元格的位置。
//该方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于将要删除的任何项。
//您的实现应该返回描述该项的最终位置和状态的布局信息。//集合视图使用此信息作为任何动画的结束点。(动画的起点是物品的当前位置。)
//如果你返回nil,布局对象对动画的开始点和结束点使用相同的属性。
//此方法的默认实现将返回nil。
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;

//检索即将从集合视图中删除的补充视图的最终布局信息。
//一个布局属性对象,用于描述补充视图的位置,以作为动画删除的结束点。
//这个方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于将要删除的任何补充视图。
//您的实现应该返回描述视图的最终位置和状态的布局信息。
//集合视图使用此信息作为任何动画的结束点。(动画的起点是视图的当前位置。)
//如果你返回nil,布局对象对动画的开始点和结束点使用相同的属性。
//此方法的默认实现将返回nil。
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;

//检索即将从集合视图中移除的装饰视图的最终布局信息。
//一个布局属性对象,它描述装饰视图的位置,用于动画化其移除。
//这个方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于任何即将被删除的装饰视图。
//您的实现应该返回描述视图的最终位置和状态的布局信息。
//集合视图使用此信息作为任何动画的结束点。(动画的起点是视图的当前位置。)
//如果你返回nil,布局对象对动画的开始点和结束点使用相同的属性。
//此方法的默认实现将返回nil。 
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;

//当项位于集合视图边界中的指定位置时,检索项的索引路径。
//与集合视图中指定位置对应的索引路径。
//在项目的交互移动过程中,
//此方法将集合视图的边界矩形中的点映射到与这些点的位置对应的索引路径。
//此方法的默认实现在指定位置搜索现有单元格并返回该单元格的索引路径。
//如果在同一位置有多个单元格,则该方法返回最上面的单元格,
//即zIndex布局属性值最大的单元格。
//您可以根据需要重写此方法,以更改确定索引路径的方式。
//例如,您可以返回zIndex值最低而不是最高的单元格的索引路径。
//如果重写此方法,则不需要调用super。
- (NSIndexPath *)targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath 
        withPosition:(CGPoint)position;

5、使布局无效的方法:

#pragma mark ------- Invalidating the layout
//使当前布局失效并触发布局更新。
//你可以在任何时候调用这个方法来更新布局信息。
//此方法使集合视图本身的布局无效,并立即返回。
//因此,您可以从同一代码块多次调用此方法,而不会触发多次布局更新。
//实际的布局更新发生在下一个视图布局更新周期。
//如果重写此方法,则必须在实现中的某个位置调用super。
- (void)invalidateLayout;

//使用 所提供的上下文对象中的信息 使当前布局失效。
//这个方法的默认实现使用UICollectionViewLayoutInvalidationContext类的基本属性来优化布局过程。
//如果您为布局定义了一个自定义上下文对象,
//请重写此方法并将上下文对象的任何自定义属性应用到布局计算中。
//如果重写此方法,则必须在实现中的某个位置调用super。
- (void)invalidateLayoutWithContext:(UICollectionViewLayoutInvalidationContext *)context;

// 返回在为布局创建无效上下文时要使用的类。 
//如果你子类化UICollectionViewLayout并使用一个自定义的
//无效上下文对象来提高布局更新的性能,重写这个方法并返回
//你的UICollectionViewLayoutInvalidationContext子类。
//当集合视图需要使布局无效时,它使用您提供的类来创建适当的无效上下文对象。
@property(class, nonatomic, readonly) Class invalidationContextClass;

//询问布局对象新的边界是否需要更新布局。
//如果集合视图需要更新布局,则为YES;如果布局不需要更改,则为NO。
//此方法的默认实现返回NO。子类可以覆盖它,
//并根据集合视图边界的更改是否需要更改单元格和补充视图的布局来返回适当的值。
//如果集合视图的边界发生了变化并且该方法返回YES,
//集合视图将通过调用invalidatelayoutithcontext:方法使布局失效。
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;

//检索一个上下文对象,该对象定义了在发生边界更改时应更改的布局部分。
//一个无效上下文,用于描述需要进行的更改。不返回nil。
//此方法的默认实现创建一个由invalidationContextClass类方法提供的类实例并返回它。
//如果你想在你的布局中使用一个自定义的无效上下文对象,
//总是重写这个方法并返回你的自定义类。
//如果要创建和配置自定义失效上下文以响应边界更改,则可以覆盖此方法。
//如果重写此方法,则必须首先调用super以获取要返回的无效上下文对象。
//获得该对象后,设置任何自定义属性并返回它。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForBoundsChange:(CGRect)newBounds;

// 询问布局对象对自定大小单元格的更改是否需要布局更新。 
//如果该布局应该无效,则为YES;如果不应该无效,则为NO。
//当集合视图包含自调整大小的单元格时,
//单元格在应用这些属性之前有机会修改自己的布局属性。
//自调整大小的单元格可以这样做,以指定与布局对象提供的单元格不同的单元格大小。
//当单元格提供不同的属性集时,
//集合视图调用此方法来确定单元格的更改是否需要更大的布局刷新。
//如果您正在实现自定义布局,
//则可以覆盖此方法并使用它来确定是否应该基于指定的属性使布局失效。
//此方法的默认实现返回NO。
- (BOOL)shouldInvalidateLayoutForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes 
     withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes;

//检索一个上下文对象,该对象标识应根据动态单元格更改而更改的布局部分。
//一个无效上下文,其中包含关于需要对布局进行哪些更改的信息。
//此方法的默认实现创建一个由invalidationContextClass类方法提供的类实例并返回它。
//如果你想在你的布局中使用一个自定义的无效上下文对象,
//总是重写这个方法并返回你的自定义类。
//子类可以重写此方法,并在返回该方法之前使用它执行无效上下文的附加配置。
//在自定义实现中,调用super,以便父类可以执行对象的基本配置。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes 
    withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes;

//检索一个上下文对象,该对象标识在布局中以交互方式移动的项。
//一个无效上下文,其中包括有关需要对布局进行哪些更改的信息。
//当一个或多个项目的交互移动正在进行时,布局对象使用此方法检索无效上下文。
//默认实现创建invalidationContextClass类方法提供的类的实例,
//用提供的信息填充它,并返回它。
//如果你想在你的布局中使用一个自定义的无效上下文对象,
//总是重写这个方法并返回你的自定义类。
//子类可以重写此方法,并在返回该方法之前使用它执行无效上下文的附加配置。
//在自定义实现中,调用super,以便父类可以执行对象的基本配置。
//targetIndexPaths(目标索引路径): 正在移动的项的当前位置。
//targetPosition(目标位置) : 集合视图坐标系中的点,它是项目的潜在放置点。
//previousIndexPaths(以前的索引路径): 正在移动的项的先前位置。
//previousPosition( 先前位置 ):  集合视图坐标系中的前一个点。
//这是以前用于确定项目的投放点的点。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForInteractivelyMovingItems:(NSArray<NSIndexPath *> *)targetIndexPaths 
     withTargetPosition:(CGPoint)targetPosition                                                           
       previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths                                                                           
        previousPosition:(CGPoint)previousPosition;

// 检索一个上下文对象,该对象标识已移动的项 
//一个无效上下文,其中包含关于需要对布局进行哪些更改的信息。
//当一个或多个项目的交互移动(因为移动成功或因为用户取消)结束时,
//布局对象使用此方法检索无效上下文。
//默认实现创建invalidationContextClass类方法提供的类的实例,
//用提供的信息填充它,并返回它。
//如果你想在你的布局中使用一个自定义的无效上下文对象,
//总是重写这个方法并返回你的自定义类。
//子类可以重写此方法,并在返回该方法之前使用它执行无效上下文的附加配置。
//在自定义实现中,调用super,以便父类可以执行对象的基本配置。
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:(NSArray<NSIndexPath *> *)indexPaths                                                                                                   
      previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths 
         movementCancelled:(BOOL)movementCancelled;

6、协调动画变化的方法:

#pragma mark ------- Coordinating animated changes
//为视图边界的动画更改或项的插入或删除准备布局对象。
//集合视图在对视图的边界执行任何动画更改之前,
//或者在动画插入或删除项之前调用此方法。
//这个方法是布局对象执行任何计算的机会,为这些动画变化做准备。
//具体来说,可以使用此方法计算插入或删除项的初始或最终位置,
//以便在请求时返回这些值。
//您还可以使用此方法来执行其他动画。
//您所创建的任何动画都将添加到用于处理插入、删除和边界更改的动画块中。
- (void)prepareForAnimatedBoundsChange:(CGRect)oldBounds;

//在对视图的边界进行任何动画更改之后或在插入或删除项之后清理。
//集合视图在创建用于更改视图边界的动画之后,
//或者在动画插入或删除项之后调用此方法。
//该方法是布局对象执行与这些操作相关的任何清理的机会。
//您还可以使用此方法来执行其他动画。
//您所创建的任何动画都将添加到用于处理插入、删除和边界更改的动画块中。
- (void)finalizeAnimatedBoundsChange;

7、在布局之间转换的方法:

#pragma mark ------- Transitioning between layouts
//告诉布局对象准备安装为集合视图的布局。
//在执行布局转换之前,集合视图调用此方法,
//以便布局对象可以执行生成布局属性所需的任何初始计算。
- (void)prepareForTransitionFromLayout:(UICollectionViewLayout *)oldLayout;

//告诉布局对象它将作为集合视图的布局被删除。
//在执行布局转换之前,集合视图调用此方法,
//以便布局对象可以执行生成布局属性所需的任何初始计算。
- (void)prepareForTransitionToLayout:(UICollectionViewLayout *)newLayout;

//告诉布局对象在转换动画发生之前执行任何最后步骤。
//集合视图在收集了执行从一个布局转换到另一个布局所需的所有布局属性后调用此方法。
//你可以使用这个方法来清理你的prepareForTransitionFromLayout:
//或prepareForTransitionToLayout:方法的实现所创建的任何数据结构或缓存。
- (void)finalizeLayoutTransition;

8、注册装饰视图的方法:

#pragma mark ------- Registering decoration views
// 注册一个类,用于为集合视图创建装饰视图。 
//该方法使布局对象有机会注册一个装饰视图,以便在集合视图中使用。
//装饰视图为部分或整个集合视图提供视觉装饰,但不绑定到集合视图数据源提供的数据。
//您不需要显式地创建装饰视图。
//注册一个后,就由布局对象来决定何时需要装饰视图,
//并从其layoutAttributesForElementsInRect:方法中返回相应的布局属性。
//对于指定装饰视图的布局属性,集合视图创建(或重用)一个视图,
//并根据注册的信息自动显示它。
//如果您之前注册了具有相同类型字符串的类或nib文件,
//则在viewClass参数中指定的类将替换旧的条目。
//如果你想取消装饰视图的注册,你可以为viewClass指定nil。
- (void)registerClass:(Class)viewClass 
forDecorationViewOfKind:(NSString *)elementKind;

//注册一个nib文件,用于为集合视图创建装饰视图。
//该方法使布局对象有机会注册一个装饰视图,以便在集合视图中使用。
//装饰视图为部分或整个集合视图提供视觉装饰,但不绑定到集合视图数据源提供的数据。
//您不需要显式地创建装饰视图。
//注册一个后,就由布局对象来决定何时需要装饰视图,
//并从其layoutAttributesForElementsInRect:方法中返回相应的布局属性。
//对于指定装饰视图的布局属性,集合视图创建(或重用)一个视图,
//并根据注册的信息自动显示它。
//如果您之前注册了具有相同类型字符串的类或nib文件,
//则在viewClass参数中指定的类将替换旧的条目。
//如果你想取消装饰视图的注册,你可以为viewClass指定nil。
- (void)registerNib:(UINib *)nib 
forDecorationViewOfKind:(NSString *)elementKind;

9、支持从右向左布局的方法:

#pragma mark ------- Supporting right-to-left layouts
// 设计自定义布局时使用的语言方向。
//此属性的默认值是与主包的开发区域相关联的语言使用的布局方向。
//子类可以重写此属性并返回不同的值。 
@property(nonatomic, readonly) UIUserInterfaceLayoutDirection developmentLayoutDirection;

//一个布尔值,指示是否在适当的时间自动翻转水平坐标系统。
//开发过程中使用的语言自然会影响您在配置布局对象时所做的决策。
//当您使用从左到右的语言进行开发时,
//您的布局信息将自动匹配集合视图的自然坐标系统。
//然而,当用户的语言具有从右到左的方向时,
//您提供的布局信息仍然基于集合视图的自然坐标系统。
//对于使用相反方向的语言,这种差异可能会导致布局问题。
//当此属性设置为YES时,集合视图自动翻转其水平坐标系统的方向,以匹配当前语言的前沿。
//(developlayoutdirection属性指定用于设计布局的布局方向。)
//翻转水平坐标系统可以有效地翻转现有的布局信息,这应该会产生更好看的布局。
//该属性的默认值为NO。
@property(nonatomic, readonly) BOOL flipsHorizontallyInOppositeLayoutDirection;

Methods to override 要覆盖的方法

每个布局对象都应该实现以下方法:

//子类必须重写此属性,并使用它返回UICollectionView内容的宽度和高度。
//这些值表示所有内容的宽度和高度,而不仅仅是当前可见的内容。
//UICollectionView使用此信息来配置自己的内容大小,以便于滚动。
// 此方法的默认实现返回CGSizeZero。 
@property(nonatomic, readonly) CGSize collectionViewContentSize;

//子类必须重写此方法,并使用它返回视图与指定矩形相交的所有项的布局信息。
//您的实现应该返回所有视觉元素的属性,包括单元格、补充视图和装饰视图。
//创建布局属性时,始终创建表示正确元素类型(单元格、补充或装饰)的属性对象。
//集合视图区分每种类型的属性,并使用这些信息来决定创建哪些视图以及如何管理它们。
//返回指定矩形中所有单元格和视图的布局属性。
//rect  包含目标视图的矩形(在集合视图的坐标系统中指定)。
//返回的是UICollectionViewLayoutAttributes对象的数组,
//表示单元格和视图的布局信息。默认实现返回nil。
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

//检索具有相应单元格的指定索引路径上的item的布局信息。
// 返回一个布局属性对象,包含要应用于项目单元格的信息。 
//子类必须重写此方法,并使用它返回集合视图中项目的布局信息。
//使用此方法仅为具有相应单元格的项提供布局信息。
//请不要将这个方法用于补充视图或装饰视图!!
-(UICollectionViewLayoutAttributes *)
    layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

//检索指定补充视图的布局属性。
//一个布局属性对象,包含应用到补充视图的信息。
//如果布局对象定义了任何补充视图,则必须重写此方法并使用它返回这些视图的布局信息。
//elementKind 标识补充视图类型的字符串。
//indexPath  视图的索引路径.
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind
     atIndexPath:(NSIndexPath *)indexPath;

//检索指定装饰视图(Decoration View)的布局属性.
// 布局属性对象,包含要应用于装饰视图的信息。 
//如果布局对象定义了任何装饰视图,则必须重写此方法并使用它来返回这些视图的布局信息。
//elementKind 标识 装饰视图(Decoration View)类型的字符串。
//indexPath  视图的索引路径.
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind 
      atIndexPath:(NSIndexPath *)indexPath;

// 询问布局对象新的边界是否需要布局更新。 
//如果集合视图需要更新布局,则为YES;如果布局不需要更改,则为NO。
//此方法的默认实现返回NO。子类可以覆盖它,
//并根据集合视图边界的更改是否需要更改单元格和补充视图的布局来返回适当的值。
//如果集合视图的边界发生了变化并且该方法返回YES,
//集合视图将通过调用invalidatelayoutithcontext:方法使布局失效。
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;

这些方法提供了集合视图在屏幕上放置内容所需的基本布局信息。如果你的布局不支持补充视图或装饰视图,就不要实现相应的方法。

当集合视图中的数据发生变化,要插入或删除项时,集合视图要求其布局对象更新布局信息。具体来说,任何移动、添加或删除的项都必须更新其布局信息,以反映其新位置。对于移动的项,集合视图使用标准方法检索项的更新布局属性。对于插入或删除的项,集合视图调用一些不同的方法,你应该覆盖这些方法来提供适当的布局信息:

//检索插入到集合视图中的项的起始布局信息。
//一个布局属性对象,用于描述要放置相应单元格的位置。
//该方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于即将插入的任何项。
//您的实现应该返回描述该项的初始位置和状态的布局信息。
//集合视图使用此信息作为任何动画的起点。(动画的终点是项目在集合视图中的新位置。)
//如果返回nil,布局对象将使用项目的final属性作为动画的起点和终点。
//此方法的默认实现将返回nil。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;

//检索即将从集合视图中删除的项的最终布局信息。
//一个布局属性对象,描述要用作动画删除单元格的终点的单元格的位置。
//该方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于将要删除的任何项。
//您的实现应该返回描述该项的最终位置和状态的布局信息。
//集合视图使用此信息作为任何动画的结束点。(动画的起点是物品的当前位置。)
//如果你返回nil,布局对象对动画的开始点和结束点使用相同的属性。
//此方法的默认实现将返回nil。
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;

//检索插入到集合视图中的补充视图的起始布局信息。
//一个布局属性对象,它描述放置相应补充视图的位置。
//该方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于即将插入的任何补充视图。
//您的实现应该返回描述视图初始位置和状态的布局信息。
//集合视图使用这些信息作为任何动画的起点。(动画的结束点是视图在集合视图中的新位置.)
//如果你返回nil,布局对象使用项目的final属性作为动画的开始点和结束点。
//此方法的默认实现将返回nil。
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;

//检索即将从集合视图中删除的补充视图的最终布局信息。
//一个布局属性对象,用于描述补充视图的位置,以作为动画删除的结束点。
//这个方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于将要删除的任何补充视图。
//您的实现应该返回描述视图的最终位置和状态的布局信息。
//集合视图使用此信息作为任何动画的结束点。(动画的起点是视图的当前位置。)
//如果你返回nil,布局对象对动画的开始点和结束点使用相同的属性。
//此方法的默认实现将返回nil。
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;

// 检索要插入到集合视图中的装饰视图的起始布局信息。 
// 布局属性对象,用于描述放置相应装饰视图的位置。 
//这个方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于任何即将插入的装饰视图。
//您的实现应该返回描述视图初始位置和状态的布局信息。
//集合视图使用这些信息作为任何动画的起点。(动画的结束点是视图在集合视图中的新位置。)
//如果你返回nil,布局对象使用项目的final属性作为动画的开始点和结束点。
//此方法的默认实现将返回nil。
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;

//检索即将从集合视图中移除的装饰视图的最终布局信息。
//一个布局属性对象,它描述装饰视图的位置,用于动画化其移除。
//这个方法在prepareForCollectionViewUpdates方法之后和
//finalizeCollectionViewUpdates方法之前被调用,用于任何即将被删除的装饰视图。
//您的实现应该返回描述视图的最终位置和状态的布局信息。
//集合视图使用此信息作为任何动画的结束点。(动画的起点是视图的当前位置。)
//如果你返回nil,布局对象对动画的开始点和结束点使用相同的属性。
//此方法的默认实现将返回nil。 
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;

除了这些方法之外,您还可以重写prepareForCollectionViewUpdates:来处理 任何与布局相关的准备工作。您也可以覆盖 [finalizeCollectionViewUpdates[() 方法,并使用它将动画添加到整个动画块中,或实现任何与最终布局相关的任务。

//通知布局对象集合视图的内容即将更改
//插入或删除项目时,集合视图会通知其布局对象,以便根据需要调整布局。
//这个过程的第一步是调用这个方法,让布局对象知道预期会发生什么变化。之后,
//将进行其他调用,以收集将在集合视图周围设置动画的插入、删除和移动项目的布局信息。
//updateItems  标识正在进行的更改的UICollectionViewUpdateItem对象数组。
- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;

//执行在集合视图更新期间所需的任何其他动画或清理。
//集合视图调用此方法作为将任何更改动画化之前的最后一步。
//此方法在用于执行所有插入、删除和移动动画的动画块中调用,
//因此您可以根据需要使用此方法创建其他动画。
//否则,您可以使用它来执行与管理布局对象的状态信息相关的任何最后一分钟的任务。
- (void)finalizeCollectionViewUpdates;
使用失效上下文优化布局性能

在设计自定义布局时,您可以通过仅使布局中实际更改的部分无效来提高性能。当您更改项时,调用invalidateLayout方法将强制集合视图重新计算其所有布局信息并重新应用它。更好的解决方案是只重新计算更改的布局信息,这正是无效上下文允许您做的事情。无效上下文允许您指定布局的哪些部分被更改。然后,布局对象可以使用该信息来最小化它重新计算的数据量

要为你的布局定义一个自定义的无效上下文,子类化UICollectionViewLayoutInvalidationContext类。在子类中,定义自定义属性,这些属性表示布局数据中可以独立重新计算的部分。当你需要在运行时使布局失效时,创建一个invalidation context子类的实例,根据布局信息的变化配置自定义属性,并将该对象传递给布局的invalidateLayoutWithContext:
方法。该方法的自定义实现可以使用失效上下文中的信息仅重新计算已更改的布局部分

如果你为你的布局对象定义了一个自定义的无效上下文类,你也应该重写invalidationContextClass 方法并返回你的自定义类。当集合视图需要无效上下文时,它总是创建您指定的类的实例。从此方法返回您的自定义子类,确保您的布局对象始终具有它所期望的无效上下文

UICollectionViewLayoutAttributes (布局属性)

#pragma mark -----访问布局属性 
@property (nonatomic) CGRect frame;
@property (nonatomic) CGRect bounds;
@property (nonatomic) CGPoint center;
@property (nonatomic) CGSize size;
//项目的三维变换。
@property (nonatomic) CATransform3D transform3D;
//项目的仿射变换。 
@property (nonatomic) CGAffineTransform transform;
@property (nonatomic) CGFloat alpha;
// 指定项目在z轴上的位置。 默认值为0
@property (nonatomic) NSInteger zIndex; 
//作为优化,UICollectionView可能不会为隐藏属性为YES的项创建视图
@property (nonatomic, getter=isHidden) BOOL hidden; 
#pragma mark -----识别被引用的项目
@property (nonatomic, strong) NSIndexPath *indexPath;
//项目的类型。
//可以使用此属性中的值来区分布局属性是用于单元格、补充视图还是装饰视图。
@property (nonatomic, readonly) UICollectionElementCategory representedElementCategory;
//目标视图的特定布局标识符。
//您可以使用此属性中的值来标识与属性关联的补充视图或装饰视图的特定用途。
//如果representtedelementcategory属性包含值UICollectionElementCategoryCell,
//则此属性为nil。
@property (nonatomic, readonly, nullable) NSString *representedElementKind; 
#pragma mark -----创建布局属性
//使用此方法可在集合视图中为单元格创建布局属性对象。
+ (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath;
//使用此方法为集合视图中的补充视图创建布局属性对象。
//与单元格一样,补充视图表示由集合视图的数据源管理的数据。
//但与单元格不同的是,补充视图通常是为特殊目的而设计的。
//例如,页眉和页脚视图的布局与单元格不同,可以为单个部分提供,
//也可以为整个集合视图提供。
//由您决定如何使用indexPath参数来标识给定的补充视图。
//通常,使用elementKind参数来标识补充视图的类型,
//使用indexPath信息来区分该视图的不同实例。
+ (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind withIndexPath:(NSIndexPath *)indexPath;
//使用此方法为集合视图中的装饰视图创建一个布局属性对象。
//装饰视图是一种补充视图,但不显示集合视图数据源管理的数据。
//相反,它们主要为一个部分或整个集合视图提供视觉装饰。
//由您决定如何使用indexPath参数来标识给定的装饰视图。
//通常,使用decorationViewKind参数来标识装饰视图的类型,
//使用indexPath信息来区分该视图的不同实例。
+ (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind withIndexPath:(NSIndexPath *)indexPath;

UICollectionViewUpdateItem

UICollectionViewUpdateItem 描述对集合视图中的项所做的单个更改的对象

您不必直接创建该类的实例。当更新其内容时,集合视图对象创建它们并将它们传递给布局对象的prepareForCollectionViewUpdates:方法,该方法可以使用它们为即将到来的更改准备布局对象。

typedef NS_ENUM(NSInteger, UICollectionUpdateAction) {
    UICollectionUpdateActionInsert,
    UICollectionUpdateActionDelete,
    UICollectionUpdateActionReload,
    UICollectionUpdateActionMove,
    UICollectionUpdateActionNone
};
//更新之前项的索引路径。
//nil用于UICollectionUpdateActionInsert
@property (nonatomic, readonly, nullable) NSIndexPath *indexPathBeforeUpdate; 
// 更新后项的索引路径。 
//nil用于UICollectionUpdateActionDelete
@property (nonatomic, readonly, nullable) NSIndexPath *indexPathAfterUpdate; 
//正在对项目执行的操作。
@property (nonatomic, readonly) UICollectionUpdateAction updateAction;
UICollectionViewLayoutInvalidationContext 上下文对象

一个上下文对象,声明当布局失效时需要更新布局的哪些部分。

为支持无效上下文而设计的布局对象可以使用UICollectionViewLayoutInvalidationContext对象中的信息来优化它们在无效周期中的行为。您可以创建一个无效上下文对象,作为使布局对象无效的前导。在配置了无效上下文对象之后,将其传递给布局对象的invalidatelayoutithcontext:方法,该方法负责使用上下文对象有效地更新布局。集合视图还创建无效上下文以响应特定的更改。例如,当您更改布局或数据源对象、插入或删除项以及调用reloadData方法时,它会创建一个无效上下文。

如果你创建自己的自定义布局对象,你可以子类化UICollectionViewLayoutInvalidationContext,并添加属性来指定布局数据的哪些方面可以单独失效。然后,必须设计布局对象以检查这些属性并适当地更新布局

有关如何在布局对象中支持自定义失效上下文的更多信息,请参见UICollectionViewLayout

#pragma mark -----使集合视图数据无效
//一个布尔值,指示所有布局数据都应标记为无效。
//您不必自己设置此属性。
//集合视图将其设置为响应特定类型的布局失效场景。
//例如,当您更改当前布局对象、更改集合视图的数据源
//或调用reloadData方法并随后请求布局失效上下文时,
//集合视图将其设置为YES。
//如果此属性设置为YES,布局对象应该重新计算所有与布局相关的数据。
@property (nonatomic, readonly) BOOL invalidateEverything; 
//一个布尔值,指示布局是否应请求新的section和item计数。
//您不必自己设置此属性。集合视图将其设置为响应特定类型的布局失效场景。
//例如,当您插入或删除项或调用集合视图的reloadData方法时,
//集合视图将其设置为YES。
//如果此属性设置为YES,布局对象应该查询它的委托以获得部分和项的数量,
//并根据新的项的数量更新其布局。
@property (nonatomic, readonly) BOOL invalidateDataSourceCounts; 
#pragma mark -----使内容区无效
//要应用于集合视图的内容偏移量的增量值。
//使用此属性可更新集合视图的内容偏移量。
//此属性的默认值是CGPointZero。
//更改该值会导致集合视图将指定的x和y值添加到其contenttoffset属性中。
//因此,正值增加内容偏移量,负值减少内容偏移量。
@property (nonatomic) CGPoint contentOffsetAdjustment; 
//要应用于集合视图的内容大小的增量值。
//使用此属性可更新集合视图内容区域的大小。
//该属性的默认值是CGSizeZero。
//更改该值会导致集合视图将指定的高度和宽度值添加到其contentSize属性中。
//因此,正值使内容面积增大,负值使内容面积缩小。
@property (nonatomic) CGSize contentSizeAdjustment; 
#pragma mark -----使特定项目无效
//将位于指定索引路径的单元格添加到无效项列表。
//调用此方法可识别需要更新的布局中的特定单元格。
//您指定的单元格将在invalidatedItemIndexPaths属性中添加到数组中。
- (void)invalidateItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths ;
//将指定索引路径处的补充视图添加到无效项列表。
//调用此方法来识别需要更新的布局的特定补充视图。
//您指定的视图将在invalidatedcomplementary indexpaths属性中添加到字典中。
//您指定的所有视图都应该是您在elementKind参数中指定的类型。
//如果使用相同的elementKind参数值调用此方法两次或多次,
//则该方法将新的索引路径与先前指定的索引路径合并。
- (void)invalidateSupplementaryElementsOfKind:(NSString *)elementKind atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
//将指定索引路径处的装饰视图添加到无效项列表。
//调用此方法来识别布局属性发生变化的特定装饰视图。
//您指定的视图将在invalidatedDecorationIndexPaths属性中添加到字典中。
//您指定的所有视图都应该是您在elementKind参数中指定的类型。//如果使用相同的elementKind参数值调用此方法两次或多次,
//则该方法将新的索引路径与先前指定的索引路径合并。
- (void)invalidateDecorationElementsOfKind:(NSString *)elementKind atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
//表示无效单元格的索引路径数组。
//数组包含零个或多个NSIndexPath对象,每个NSIndexPath对象表示一个布局改变的单元格。
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *invalidatedItemIndexPaths;
//标识已失效的补充视图的字典。
//这个字典中的键是无效补充视图的元素类型字符串。
//每个键的值是一个NSIndexPath对象数组,表示哪些特定的补充视图有布局更改。
@property (nonatomic, readonly, nullable) NSDictionary<NSString *, NSArray<NSIndexPath *> *> *invalidatedSupplementaryIndexPaths; 
//标识无效装饰视图的字典。
//这个字典中的键是无效装饰视图的元素类型字符串。
//每个键的值是一个NSIndexPath对象数组,表示哪些特定的装饰视图有布局变化。
@property (nonatomic, readonly, nullable) NSDictionary<NSString *, NSArray<NSIndexPath *> *> *invalidatedDecorationIndexPaths; 
#pragma mark -----无效项目的顺序
//索引路径数组,表示集合视图中移动项的先前位置。
//当交互移动正在进行或刚刚结束时,此属性将被填充。
//将此属性与targetIndexPathsForInteractivelyMovingItems属性一起使用,
//以确定需要对受影响的项进行哪些更改。对于大多数其他更新,此属性的值为nil。
@property (nonatomic, readonly, copy, nullable) NSArray<NSIndexPath *> *previousIndexPathsForInteractivelyMovingItems; 
//索引路径数组,表示集合视图中移动项的新位置。
//当交互移动正在进行或刚刚结束时,此属性将被填充。
//将此属性与previousIndexPathsForInteractivelyMovingItems属性一起使用,
//以确定需要对受影响的项进行哪些更改。对于大多数其他更新,此属性的值为nil。
@property (nonatomic, readonly, copy, nullable) NSArray<NSIndexPath *> *targetIndexPathsForInteractivelyMovingItems; 
//用于确定移动项目位置的当前点。
//当交互移动正在进行或刚刚结束时,此属性将被填充。该值表示用于确定
//targetIndexPathsForInteractivelyMovingItems属性中的新索引路径的点。
//您可以根据需要使用这个点来计算项目在布局中的位置。
@property (nonatomic, readonly) CGPoint interactiveMovementTarget;

七、 UICollectionViewFlowLayout 流布局

UICollectionViewFlowLayout 继承 UICollectionViewLayout

1、配置滚动方向

//这个属性的默认值是UICollectionViewScrollDirectionVertical。
@property(nonatomic) UICollectionViewScrollDirection scrollDirection;

2、配置item间距

//minimumLineSpacing 最小行距
@property (nonatomic) CGFloat minimumLineSpacing;
//minimumInteritemSpacing 在同一行的 item 之间的最小间距
//两个item之间的最小列距
@property (nonatomic) CGFloat minimumInteritemSpacing;
//如果委托未实现collectionView:layout:sizeForItemAtIndexPath:方法,
//则流布局将使用此属性中的值来设置每个单元格的大小。
//这导致所有单元格都具有相同的大小。
@property (nonatomic) CGSize itemSize;
//当单元格动态调整其大小时,提供估计的单元格大小可以提高集合视图的性能。
//估计值让集合视图推迟一些计算,以确定其内容的实际大小。
//不在屏幕上的单元格被假定为估计高度。
//该属性的默认值是CGSizeZero。将其设置为任何其他值,
//如UICollectionViewFlowLayoutAutomaticSize,会导致集合视图使用
//单元格的preferredLayoutAttributesFittingAttributes:方法
//查询每个单元格的实际大小。
//如果所有单元格大小相同,则使用itemSize属性而不是此属性来指定单元格大小。
@property (nonatomic) CGSize estimatedItemSize;
@property (nonatomic) UICollectionViewFlowLayoutSectionInsetReference sectionInsetReference;//iOS 11.0+;
@property (nonatomic) UIEdgeInsets sectionInset;
@property (nonatomic) UICollectionViewFlowLayoutSectionInsetReference sectionInsetReference;
//用于自调整单元格大小的占位符大小。
//将此常量设置为estimatedItemSize属性的值,
//以便为您的集合视图启用自调整单元格大小。
//这是一个非零的占位符值,它告诉集合视图使用单元格的
//preferredLayoutAttributesFittingAttributes:方法
//查询每个单元格的实际大小。
UIKIT_EXTERN const CGSize UICollectionViewFlowLayoutAutomaticSize API_AVAILABLE(ios(10.0));

3、配置headers 和 footers

//section headers 的默认大小。
//如果委托未实现collectionView:layout:referenceSizeForHeaderInSection:方法,
//流布局对象使用该属性中设置的默认头大小。
//默认的大小值是(0,0)。
@property (nonatomic) CGSize headerReferenceSize;
//section footers的默认大小。
//如果委托未实现collectionView:layout:referenceSizeForFooterInSection:
方法,
//流布局对象使用该属性中设置的默认头大小。
//默认的大小值是(0,0)。
@property (nonatomic) CGSize footerReferenceSize;

4、固定headers 和 footers

//一个布尔值,指示滚动时头是否固定在集合视图边界的顶部。
//当此属性为YES时,section headers视图将随内容滚动,
//直到它们到达屏幕顶部,此时它们将固定在集合视图的上界。
//每个滚动到屏幕顶部的新标题视图都会将先前固定的标题视图推到屏幕外。
//该属性的默认值为NO。
@property (nonatomic) BOOL sectionHeadersPinToVisibleBounds;
//一个布尔值,指示滚动时页脚是否固定在集合视图边界的底部。
//当此属性为YES时,节页脚视图将随内容滚动,
//直到它们到达屏幕底部,此时它们将固定在集合视图的下界。
//每个滚动到屏幕底部的新页脚视图都会将先前固定的页脚视图推到屏幕外。
//该属性的默认值为NO。
@property (nonatomic) BOOL sectionFootersPinToVisibleBounds;
UICollectionViewDelegateFlowLayout

1、获取项目的大小

// 向delegate询问指定项目单元格的大小。
//指定项的宽度和高度。两个值都必须大于0。
//如果不实现此方法,流布局将使用itemSize属性中的值来设置项的大小。
//此方法的实现可以返回一组固定的大小,也可以根据单元格的内容动态调整大小。
- (CGSize)collectionView:(UICollectionView *)collectionView
   layout:(UICollectionViewLayout*)collectionViewLayout 
        sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

2、获取分区间距

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView 
  layout:(UICollectionViewLayout*)collectionViewLayout 
      insetForSectionAtIndex:(NSInteger)section;
//同一个section中相邻两line之间的最小距离
- (CGFloat)collectionView:(UICollectionView *)collectionView 
   layout:(UICollectionViewLayout*)collectionViewLayout 
       minimumLineSpacingForSectionAtIndex:(NSInteger)section;
//
- (CGFloat)collectionView:(UICollectionView *)collectionView 
  layout:(UICollectionViewLayout*)collectionViewLayout 
   minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;

3、获取header 和 footer 大小

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
UICollectionViewFlowLayoutInvalidationContext

流布局对象在需要使其内容失效以响应更改时创建该类的实例。您还可以在手动使流布局无效时创建实例。

UICollectionViewFlowLayoutInvalidationContext 继承UICollectionViewLayoutInvalidationContext

//一个布尔值,指示是否重新计算布局中项和视图的大小。
//该属性的默认值为NO。如果由于更改任何项的大小而使布局无效,
//则将此属性设置为YES。
//当此属性设置为YES时,流布局对象将重新计算其项和视图的大小,
//并根据需要查询委托对象以获得该信息。
@property (nonatomic) BOOL invalidateFlowLayoutDelegateMetrics; 
//一个布尔值,指示是否重新计算布局中项和视图的布局属性。
//该属性的默认值为NO。如果项目在屏幕上的位置发生变化,则将此属性设置为YES。
//例如,当集合视图的边界发生影响列或行中项数的变化时,
//流布局对象将此属性设置为YES。
//当此属性设置为YES时,流布局对象将为其项和视图重新计算布局属性。
//如果invalidateFlowLayoutDelegateMetrics属性被设置为NO,
//它将重新计算该信息而不要求新的大小信息。
@property (nonatomic) BOOL invalidateFlowLayoutAttributes; 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容