#if USE_UIKIT_PUBLIC_HEADERS || !__has_include(<UIKitCore/UICollectionViewLayout.h>)
//
// UICollectionViewLayout.h
// UIKit
//
// Copyright (c) 2011-2018 Apple Inc. All rights reserved.
//
#import <UIKit/UIKitDefines.h>
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <QuartzCore/CATransform3D.h>
#import <UIKit/UIDynamicBehavior.h>
#import <UIKit/UIInterface.h>
NS_ASSUME_NONNULL_BEGIN
/* 元素类别 <枚举> */
typedef NS_ENUM(NSUInteger, UICollectionElementCategory) {
UICollectionElementCategoryCell, /// Cell
UICollectionElementCategorySupplementaryView, /// 补充视图
UICollectionElementCategoryDecorationView /// 装饰视图
};
@class UICollectionViewLayoutAttributes;
@class UICollectionView;
@class UINib;
#pragma mark - 集合视图布局属性 Class
#pragma mark -
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewLayoutAttributes : NSObject <NSCopying, UIDynamicItem>
@property (nonatomic) CGRect frame;
@property (nonatomic) CGPoint center;
@property (nonatomic) CGSize size;
@property (nonatomic) CATransform3D transform3D;
@property (nonatomic) CGRect bounds NS_AVAILABLE_IOS(7_0);
@property (nonatomic) CGAffineTransform transform NS_AVAILABLE_IOS(7_0);
@property (nonatomic) CGFloat alpha;
/// Z轴上的位置(默认:0)
@property (nonatomic) NSInteger zIndex;
@property (nonatomic, getter=isHidden) BOOL hidden;
@property (nonatomic, strong) NSIndexPath *indexPath;
/// 元素类别(区分布局属性是用于单元格/补充视图/装饰视图)
@property (nonatomic, readonly) UICollectionElementCategory representedElementCategory;
/// 使用此属性中的值标识补充视图/装饰视图的特定用途(representedElementCategory == UICollectionElementCategoryCell 时,此值为nil)
@property (nonatomic, readonly, nullable) NSString *representedElementKind;
/* 实例化 */
// 创建时 指定索引
+ (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath;
// 创建时 指定补充视图和索引
+ (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind withIndexPath:(NSIndexPath *)indexPath;
// 创建时 指定装饰视图和所用
+ (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind withIndexPath:(NSIndexPath *)indexPath;
@end
/* 更新动作 <枚举> */
typedef NS_ENUM(NSInteger, UICollectionUpdateAction) {
UICollectionUpdateActionInsert, /// 将Item插入到集合视图中
UICollectionUpdateActionDelete, /// 从集合视图中删除该Item
UICollectionUpdateActionReload, /// 重新加载Item(包括删除后插入Item)
UICollectionUpdateActionMove, /// 将Item从当前位置移动到新位置
UICollectionUpdateActionNone /// 不采取任何操作
};
#pragma mark - 集合视图更新Item Class
#pragma mark -
/*
- 概述
无需实例化,更新Item时,CollectionView会自动创建,并将其传递给布局对象的 prepareForCollectionViewUpdates: 方法
*/
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewUpdateItem : NSObject
/// 更新之前Item的索引(如果updateAction == UICollectionUpdateActionInsert,此值为nil)
@property (nonatomic, readonly, nullable) NSIndexPath *indexPathBeforeUpdate;
/// 更新之后Item的索引(如果updateAction == UICollectionUpdateActionDelete,此值为nil)
@property (nonatomic, readonly, nullable) NSIndexPath *indexPathAfterUpdate;
/// 更新的当前动作
@property (nonatomic, readonly) UICollectionUpdateAction updateAction;
@end
#pragma mark - 集合视图无效上下文布局 Class
#pragma mark -
/*
- 一个上下文对象,声明布局失效时需要更新布局的哪些部分
*/
NS_CLASS_AVAILABLE_IOS(7_0) @interface UICollectionViewLayoutInvalidationContext : NSObject
/// 是否将所有布局数据标记为无效
@property (nonatomic, readonly) BOOL invalidateEverything;
/// 是否重新请求组和Item的个数
@property (nonatomic, readonly) BOOL invalidateDataSourceCounts;
// 指定索引的Item添加到无效列表中
- (void)invalidateItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(8_0);
// 指定索引的补充视图添加到无效列表中
- (void)invalidateSupplementaryElementsOfKind:(NSString *)elementKind atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(8_0);
// 指定索引的装饰视图添加到无效列表中
- (void)invalidateDecorationElementsOfKind:(NSString *)elementKind atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(8_0);
/// 无效列表中的Item索引
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *invalidatedItemIndexPaths NS_AVAILABLE_IOS(8_0);
/// 无效列表中的补充视图索引(键:元素类型字符串;值:索引数组)
@property (nonatomic, readonly, nullable) NSDictionary<NSString *, NSArray<NSIndexPath *> *> *invalidatedSupplementaryIndexPaths NS_AVAILABLE_IOS(8_0);
/// 无效列表中的装饰视图索引(键:元素类型字符串;值:索引数组)
@property (nonatomic, readonly, nullable) NSDictionary<NSString *, NSArray<NSIndexPath *> *> *invalidatedDecorationIndexPaths NS_AVAILABLE_IOS(8_0);
/// 调整当前集合视图的偏移量(默认:CGPointZero)
@property (nonatomic) CGPoint contentOffsetAdjustment NS_AVAILABLE_IOS(8_0);
/// 调整当前集合视图的尺寸(默认:CGSizeZero)
@property (nonatomic) CGSize contentSizeAdjustment NS_AVAILABLE_IOS(8_0);
/// Item失效之前的位置索引(支持重新排序)
@property (nonatomic, readonly, copy, nullable) NSArray<NSIndexPath *> *previousIndexPathsForInteractivelyMovingItems NS_AVAILABLE_IOS(9_0);
/// Item失效之后的位置索引
@property (nonatomic, readonly, copy, nullable) NSArray<NSIndexPath *> *targetIndexPathsForInteractivelyMovingItems NS_AVAILABLE_IOS(9_0);
/// Item当前坐标
@property (nonatomic, readonly) CGPoint interactiveMovementTarget NS_AVAILABLE_IOS(9_0);
@end
#pragma mark - 集合视图布局 Class
#pragma mark -
/*
- 为集合视图生成布局信息的抽象基类
*/
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewLayout : NSObject <NSCoding>
/* 实例化 */
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
/// 此布局作用的集合视图
@property (nullable, nonatomic, readonly) UICollectionView *collectionView;
// 废弃布局(继承需要回调父类)
- (void)invalidateLayout;
// 使用提供的上下文对象中的信息使当前布局无效(继承需要回调父类)
- (void)invalidateLayoutWithContext:(UICollectionViewLayoutInvalidationContext *)context NS_AVAILABLE_IOS(7_0);
/**
注册装饰视图
@param viewClass 用于补充视图的类
@param elementKind 装饰视图的元素种类(使用此字符串区分布局中具有不同用途的装饰视图;不能为nil且不能为空字符串)
- 此方法使布局对象有机会注册装饰视图以在集合视图中使用;装饰视图为部分或整个集合视图提供视觉装饰,但不与集合视图的数据源提供的数据相关联
- 您无需显式创建装饰视图;注册一个之后,由布局对象决定何时需要装饰视图并从其layoutAttributesForElementsInRect:方法返回相应的布局属性;对于指定装饰视图的布局属性,集合视图会创建(或重用)视图,并根据注册的信息自动显示该视图
- 如果先前使用相同类型的字符串注册了类或nib文件,则在viewClass参数中指定的类将替换旧条目;如果要取消注册装饰视图,可以为viewClass指定nil
*/
- (void)registerClass:(nullable Class)viewClass forDecorationViewOfKind:(NSString *)elementKind;
- (void)registerNib:(nullable UINib *)nib forDecorationViewOfKind:(NSString *)elementKind;
@end
#pragma mark - 布局类子类 <分类>
@interface UICollectionViewLayout (UISubclassingHooks)
#if UIKIT_DEFINE_AS_PROPERTIES
/// 返回创建布局属性对象时要使用的类(重写此方法以提供在实例化UICollectionViewLayoutAttributes实例时要使用的自定义类)
@property(class, nonatomic, readonly) Class layoutAttributesClass;
/// 返回为布局创建失效上下文时要使用的类(重写此方法以提供用于失效上下文的自定义类)
@property(class, nonatomic, readonly) Class invalidationContextClass NS_AVAILABLE_IOS(7_0);
#else
+ (Class)layoutAttributesClass;
+ (Class)invalidationContextClass NS_AVAILABLE_IOS(7_0);
#endif
/**
准备布局(告诉布局对象更新当前布局)
- 继承需要回调父类
- 集合视图在第一个布局中调用一次;布局无效之后和重新查询布局信息之前会调用一次
*/
- (void)prepareLayout;
/* UICollectionView调用这四种方法来确定布局信息 */
// 返回指定范围内所有Item的布局属性(包括Item/补充视图/装饰视图的布局属性;默认返回将要显示的区域Item布局属性)
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
// 返回指定索引的Item的布局属性(子类都应实现此方法,以按需返回特定索引路径的布局属性)
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
// 返回指定补充视图的布局属性
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
// 返回指定装饰视图的布局属性
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath;
// newBounds所在区域的Item是否需要重新布局(只要CollectionView滚动就让Cell布局失效)
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
// 返回一个上下文对象,该对象定义在发生边界更改时应更改的布局部分
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForBoundsChange:(CGRect)newBounds NS_AVAILABLE_IOS(7_0);
// 如果对自定义Item的更改需要布局更新,则询问布局对象
- (BOOL)shouldInvalidateLayoutForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes NS_AVAILABLE_IOS(8_0);
// 返回一个上下文对象,该对象标识应该响应动态单元格更改而更改的布局部分
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes NS_AVAILABLE_IOS(8_0);
// 提前返回Item要滚动到的位置(快速拖拽一次,在滑动停止之前的合适时机就会回调此方法,返回contentOffset的值)
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;
// 返回动画之后要停留的位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset NS_AVAILABLE_IOS(7_0);
/**
集合视图内容的宽高
@return 尺寸
- 子类必须重写此方法并用它来返回集合视图内容的尺寸
- 这些值表示所有内容的尺寸,而不仅仅是当前可见的内容
- 集合视图使用此信息配置其自己的内容大小以便于滚动
*/
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) CGSize collectionViewContentSize;
#else
- (CGSize)collectionViewContentSize;
#endif
/* 一般用于阿拉伯语言时从右到左的使用习惯 */
/// 动态布局方向(左对齐或右对齐;子类可以重写此方法以指定布局的实现时布局方向;默认:UIUserInterfaceLayoutDirectionLeftToRight)
@property (nonatomic, readonly) UIUserInterfaceLayoutDirection developmentLayoutDirection;
/// 是否水平旋转坐标系(默认:NO)
@property(nonatomic, readonly) BOOL flipsHorizontallyInOppositeLayoutDirection;
@end
#pragma mark - 更新支持 Class <分类>
@interface UICollectionViewLayout (UIUpdateSupportHooks)
/**
通知布局对象集合视图内容即将更改
@param updateItems 是一个UICollectionViewUpdateItem实例的数组,用于移动到新索引路径的每个元素
- 集合视图删除/插入更新时调用此方法
- 将在调用初始方法/最终布局方法之前调用,以使布局有机会对删除/插入布局属性进行批量计算
*/
- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
/**
完成 CollectionView 更新
- 在执行所有删除/插入/移动的动画回调中调用此方法,以便根据需要使用此方法创建其他动画;或使用它来执行与管理布局对象的状态信息相关的任何最后一步任务
- 集合视图将此方法作为最后一步调用,然后再将所有更改设置为动画执行
*/
- (void)finalizeCollectionViewUpdates;
/* 协调动画更改 */
// 准备布局Bounds(一般在动画Block里实现此方法,以便对视图的Bounds或Item的插入/删除进行动画更改)
- (void)prepareForAnimatedBoundsChange:(CGRect)oldBounds;
// 已经布局Bounds(在对视图边界进行动画更改之后或在Item插入/删除之后调用)
- (void)finalizeAnimatedBoundsChange;
/* 布局之间的转换 */
// 旋转动画前将要删除旧的Layout
- (void)prepareForTransitionToLayout:(UICollectionViewLayout *)newLayout NS_AVAILABLE_IOS(7_0);
// 旋转动画前将要更新Layout
- (void)prepareForTransitionFromLayout:(UICollectionViewLayout *)oldLayout NS_AVAILABLE_IOS(7_0);
// 旋转动画前执行的最后步骤(转换后在动画块内部调用)
- (void)finalizeLayoutTransition NS_AVAILABLE_IOS(7_0);
/*
- 集合视图执行动画时调用此方法集
- 对于失效前屏幕上的每个元素,调用finalLayoutAttributesForDisappearingXXX,并从屏幕上的内容到最终属性进行动画设置
- 对于失效后屏幕上的每个元素,调用initialLayoutAttributesForAppearingXXX,并从这些初始属性到最终屏幕上的动画设置
*/
// 返回要插入到集合视图中的Item起始布局信息
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
// 返回即将从集合视图中删除的Item最终布局信息
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
// 返回插入到集合视图中的补充视图的起始布局信息
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;
// 返回即将从集合视图中删除的补充视图的最终布局信息
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)elementIndexPath;
// 返回插入到集合视图中的装饰视图的起始布局信息
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;
// 返回即将从集合视图中删除的装饰视图的最终布局信息
- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;
/*
- 在block回调期间,集合视图会调用这些方法
- 返回一个索引路径数组,以指示布局正在删除/插入的视图以响应更新
*/
// 返回一组要删除的补充视图索引
- (NSArray<NSIndexPath *> *)indexPathsToDeleteForSupplementaryViewOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(7_0);
// 返回一组要删除的装饰视图索引
- (NSArray<NSIndexPath *> *)indexPathsToDeleteForDecorationViewOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(7_0);
// 返回一组要添加到布局的补充视图索引
- (NSArray<NSIndexPath *> *)indexPathsToInsertForSupplementaryViewOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(7_0);
// 返回一组要添加到布局的装饰视图索引
- (NSArray<NSIndexPath *> *)indexPathsToInsertForDecorationViewOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(7_0);
@end
#pragma mark - 重新布局 Class <分类>
@interface UICollectionViewLayout (UIReorderingSupportHooks)
// 当Item位于集合视图中的指定位置时,返回该Item的索引
- (NSIndexPath *)targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath withPosition:(CGPoint)position NS_AVAILABLE_IOS(9_0);
// 在用户以交互方式移动Item时,返回Item的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForInteractivelyMovingItemAtIndexPath:(NSIndexPath *)indexPath withTargetPosition:(CGPoint)position NS_AVAILABLE_IOS(9_0);
// 返回一个上下文对象,用于标识在布局中以交互方式移动的Item
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForInteractivelyMovingItems:(NSArray<NSIndexPath *> *)targetIndexPaths withTargetPosition:(CGPoint)targetPosition previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths previousPosition:(CGPoint)previousPosition NS_AVAILABLE_IOS(9_0);
// 返回标识已移动Item的上下文对象
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:(NSArray<NSIndexPath *> *)indexPaths previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths movementCancelled:(BOOL)movementCancelled NS_AVAILABLE_IOS(9_0);
@end
NS_ASSUME_NONNULL_END
#else
#import <UIKitCore/UICollectionViewLayout.h>
#endif
网友评论