一、UICollectionView
UICollectionView繼承自UIScrollView多律,是一種新的數(shù)據(jù)展示方式痴突。內(nèi)置的UICollectionViewFlowLayout提供了多行多列的展示方式,UICollectionViewDataSouce提供了數(shù)據(jù)源協(xié)議狼荞,UICollectionViewDelegate提供了UI交互的先關(guān)協(xié)議辽装,使用UICollectionView我們可以用很少的代碼就可以實(shí)現(xiàn)很多復(fù)雜的效果,下面是相關(guān)API以及屬性:
//直接初始化方法相味,需要提供一個(gè)Layout
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_DESIGNATED_INITIALIZER;
//從nib文件直接初始化
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
//當(dāng)前Layout
@property (nonatomic, strong) UICollectionViewLayout *collectionViewLayout;
//用戶交互Delegate
@property (nonatomic, weak, nullable) id <UICollectionViewDelegate> delegate;
//UI的數(shù)據(jù)源DataSource
@property (nonatomic, weak, nullable) id <UICollectionViewDataSource> dataSource;
//iOS10新增加的Pre-Fetching預(yù)加載協(xié)議
@property (nonatomic, weak, nullable) id<UICollectionViewDataSourcePrefetching> prefetchDataSource NS_AVAILABLE_IOS(10_0);
//是否允許預(yù)加載
@property (nonatomic, getter=isPrefetchingEnabled) BOOL prefetchingEnabled NS_AVAILABLE_IOS(10_0);
//背景圖片拾积,自動(dòng)根據(jù)collectionView的大小調(diào)整
@property (nonatomic, strong, nullable) UIView *backgroundView;
//注冊(cè)UICollectionViewCell,或其子類,并且提供一個(gè)復(fù)用標(biāo)識(shí)符拓巧,在runtime的時(shí)候會(huì)初始化這個(gè)對(duì)象
- (void)registerClass:(nullable Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
//通過nib文件注冊(cè)復(fù)用cell
- (void)registerNib:(nullable UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier;
//通過Class注冊(cè)補(bǔ)充視圖斯碌,并且指定補(bǔ)充視圖的種類
- (void)registerClass:(nullable Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
//通過nib文件注冊(cè)補(bǔ)充視圖
- (void)registerNib:(nullable UINib *)nib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)identifier;
//從復(fù)用隊(duì)列通過指定Identifier獲取復(fù)用cell
- (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
//從復(fù)用隊(duì)列通過指定Identifier獲取復(fù)用ReusableView
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
//是否允許items選中,默認(rèn)YES
@property (nonatomic) BOOL allowsSelection; // default is YES
//是否允許items多選肛度,默認(rèn)NO
@property (nonatomic) BOOL allowsMultipleSelection; // default is NO
//返回選中的index paths输拇,返回nil或者NSArray
#if UIKIT_DEFINE_AS_PROPERTIES
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedItems;
#else
- (nullable NSArray<NSIndexPath *> *)indexPathsForSelectedItems;
#endif
//選中和解選indexPath對(duì)應(yīng)item,可指定動(dòng)畫和UICollectionViewScrollPosition
- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition;
- (void)deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
//刷新數(shù)據(jù)
- (void)reloadData;
//切換當(dāng)前collectionView的layout
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated;
//切換當(dāng)前collectionView的layout贤斜,配置完成之后的block(iOS7之后可用)
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
//下面這些方法更加強(qiáng)大策吠,我們可以對(duì)布局更改后的動(dòng)畫進(jìn)行設(shè)置
//這個(gè)方法傳入一個(gè)布局策略layout,系統(tǒng)會(huì)開始進(jìn)行布局渲染瘩绒,返回一個(gè)UICollectionViewTransitionLayout對(duì)象
//這個(gè)UICollectionViewTransitionLayout對(duì)象管理動(dòng)畫的相關(guān)屬性猴抹,我們可以進(jìn)行設(shè)置
- (UICollectionViewTransitionLayout *)startInteractiveTransitionToCollectionViewLayout:(UICollectionViewLayout *)layout completion:(nullable UICollectionViewLayoutInteractiveTransitionCompletion)completion NS_AVAILABLE_IOS(7_0);
//準(zhǔn)備好動(dòng)畫設(shè)置后,我們需要調(diào)用下面的方法進(jìn)行布局動(dòng)畫的展示锁荔,之后會(huì)調(diào)用上面方法的block回調(diào)
//layout切換過渡完成
- (void)finishInteractiveTransition NS_AVAILABLE_IOS(7_0);
//取消過渡切換layout
- (void)cancelInteractiveTransition NS_AVAILABLE_IOS(7_0);
//下面是UICollectionView的狀態(tài)信息
//返回section的數(shù)量
#if UIKIT_DEFINE_AS_PROPERTIES
@property (nonatomic, readonly) NSInteger numberOfSections;
#else
- (NSInteger)numberOfSections;
#endif
//返回對(duì)應(yīng)section中item的數(shù)量
- (NSInteger)numberOfItemsInSection:(NSInteger)section;
//返回對(duì)應(yīng)indexPath的item的LayoutAttributes
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
//返回對(duì)應(yīng)indexPath的ReuseView的LayoutAttributes
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
//返回對(duì)應(yīng)point的indexPath
- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point;
//返回對(duì)應(yīng)cell的indexPath
- (nullable NSIndexPath *)indexPathForCell:(UICollectionViewCell *)cell;
//返回對(duì)應(yīng)indexPath的cell
- (nullable UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath;
//返回collectionView當(dāng)前可見的item數(shù)組和可見item的indexPath數(shù)組
#if UIKIT_DEFINE_AS_PROPERTIES
@property (nonatomic, readonly) NSArray<__kindof UICollectionViewCell *> *visibleCells;
@property (nonatomic, readonly) NSArray<NSIndexPath *> *indexPathsForVisibleItems;
#else
- (NSArray<__kindof UICollectionViewCell *> *)visibleCells;
- (NSArray<NSIndexPath *> *)indexPathsForVisibleItems;
#endif
//返回對(duì)應(yīng)indexPath的ReuseView(iOS9之后可用)
- (nullable UICollectionReusableView *)supplementaryViewForElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
//返回collectionView當(dāng)前可見的ReuseView數(shù)組
- (NSArray<UICollectionReusableView *> *)visibleSupplementaryViewsOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(9_0);
//返回collectionView當(dāng)前可見ReuseView的indexPath數(shù)組
- (NSArray<NSIndexPath *>
*)indexPathsForVisibleSupplementaryElementsOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(9_0);
//下面是UICollectionView的交互相關(guān)信息
//滾動(dòng)到指定的indexPath
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;
//插入一個(gè)section
- (void)insertSections:(NSIndexSet *)sections;
//刪除一個(gè)section
- (void)deleteSections:(NSIndexSet *)sections;
//刷新一個(gè)section
- (void)reloadSections:(NSIndexSet *)sections;
//移動(dòng)一個(gè)section到另外一個(gè)section
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;
//插入一個(gè)section
- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
//刪除一個(gè)section
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
//刷新一個(gè)section
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
//移動(dòng)一個(gè)indexPath的item到另一個(gè)indexPath的item
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;
//一次性操作插入蟀给,刪除,刷新阳堕,移動(dòng)操作
//Animates multiple insert, delete, reload, and move operations as a group
- (void)performBatchUpdates:(void (^ __nullable)(void))updates completion:(void (^ __nullable)(BOOL finished))completion; // allows multiple insert/delete/reload/move calls to be animated simultaneously. Nestable.
// 排序相關(guān)
//是否允許排序跋理,默認(rèn)YES(iOS9之后有效)
- (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
//更新item的位置
- (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition NS_AVAILABLE_IOS(9_0);
//移動(dòng)item到新的position
- (void)endInteractiveMovement NS_AVAILABLE_IOS(9_0);
//回復(fù)item到原始的position
- (void)cancelInteractiveMovement NS_AVAILABLE_IOS(9_0);
//是否記住最后操作的indexPath,默認(rèn)NO
@property (nonatomic) BOOL remembersLastFocusedIndexPath NS_AVAILABLE_IOS(9_0);
//UICollectionView 補(bǔ)充 的indexPath
@interface NSIndexPath (UICollectionViewAdditions)
//初始化indexPath
+ (instancetype)indexPathForItem:(NSInteger)item inSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
//返回IndexPath的item
@property (nonatomic, readonly) NSInteger item NS_AVAILABLE_IOS(6_0);
@end
//UICollectionViewDataSource數(shù)據(jù)源協(xié)議
@protocol UICollectionViewDataSource <NSObject>
@required
//配置UICollectionView的section對(duì)應(yīng)item的數(shù)量
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
//配置UICollectionView的item,需要提前注冊(cè)
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
//配置UICollectionView的section數(shù)量
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
//配置UICollectionView的ReuseView恬总,需要提前注冊(cè)
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
//是否可以移動(dòng)
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
//移動(dòng)indexPath的item到另一個(gè)indexPath
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath NS_AVAILABLE_IOS(9_0);
@end
//UICollectionViewDelegate UI交互協(xié)議
@protocol UICollectionViewDelegate <UIScrollViewDelegate>
@optional
//是否允許高亮
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
//已經(jīng)高亮
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
//取消高亮
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath;
//是否允許選中
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
//是否允許解選
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath; // called when the user taps on an already-selected item in multi-select mode
//已經(jīng)選中
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
//已經(jīng)解選
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
//將要顯示item(iOS8之后可用)
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);
//將要顯示SupplementaryView(iOS8之后可用)
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);
//已經(jīng)顯示item
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
//已經(jīng)顯示SupplementaryView
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
//是否允許展示copy/paste Menu
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath;
//是否可以執(zhí)行SEL
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender;
//執(zhí)行SEL
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender;
@end
二前普、UICollectionViewCell
UICollectionView為了優(yōu)化性能,item和supplementView都采用復(fù)用隊(duì)列的形式來(lái)返回壹堰,普通的補(bǔ)充視圖直接就是UICollectionReusableView及其子類拭卿,item即UICollectionViewCell屬于UICollectionReusableView的子類,下面是UICollectionReusableView的頭文件聲明:
//獲取復(fù)用標(biāo)識(shí)符reuseIdentifier
@property (nonatomic, readonly, copy, nullable) NSString *reuseIdentifier;
//從復(fù)用隊(duì)列取到collectionView之前調(diào)用贱纠,子類在重寫這個(gè)方法峻厚,完成返回之前的需要的配置
- (void)prepareForReuse;
//根據(jù)LayoutAttributes來(lái)布局當(dāng)前View,在view被添加到collectionView上但是還沒有被服用隊(duì)列返回的時(shí)候調(diào)用
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes;
// Override these methods to provide custom UI for specific layouts.
- (void)willTransitionFromLayout:(UICollectionViewLayout *)oldLayout toLayout:(UICollectionViewLayout *)newLayout;
- (void)didTransitionFromLayout:(UICollectionViewLayout *)oldLayout toLayout:(UICollectionViewLayout *)newLayout;
- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes NS_AVAILABLE_IOS(8_0);
下面是UICollectionViewCell的頭文件聲明:
//內(nèi)容視圖谆焊,子類圖需要粘貼在contentView上面
@property (nonatomic, readonly) UIView *contentView;
//設(shè)置item的選中狀態(tài)
@property (nonatomic, getter=isSelected) BOOL selected;
//設(shè)置item的高亮狀態(tài)
@property (nonatomic, getter=isHighlighted) BOOL highlighted;
//背景圖片
@property (nonatomic, strong, nullable) UIView *backgroundView;
//選中背景圖片
@property (nonatomic, strong, nullable) UIView *selectedBackgroundView;
三惠桃、UICollectionViewController
UICollectionViewContoller繼承自UIViewController,默認(rèn)實(shí)現(xiàn)了UICollectionViewDelegate和UICollectionViewDataSource辖试,提供了一種簡(jiǎn)單使用UICollectionViewContoller的方式辜王,類似于UITableViewController
//用指定的layout初始化UICollectionViewController
- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout NS_DESIGNATED_INITIALIZER;
//當(dāng)前的collectionView
@property (nullable, nonatomic, strong) __kindof UICollectionView *collectionView;
//在viewWillAppear:時(shí)是否清除選中效果,默認(rèn)YES
@property (nonatomic) BOOL clearsSelectionOnViewWillAppear;
//在導(dǎo)航過渡的時(shí)候是否使用layout剃执,在push之前設(shè)置誓禁,之后設(shè)置無(wú)效
@property (nonatomic, assign) BOOL useLayoutToLayoutNavigationTransitions NS_AVAILABLE_IOS(7_0);
//當(dāng)前的collectionViewLayout,只讀屬性
@property (nonatomic, readonly) UICollectionViewLayout *collectionViewLayout NS_AVAILABLE_IOS(7_0);
//是否允許排序肾档,默認(rèn)是YES
@property (nonatomic) BOOL installsStandardGestureForInteractiveMovement NS_AVAILABLE_IOS(9_0);
四摹恰、UICollectionViewFlowLayout
UICollectionViewFlowLayout是系統(tǒng)自帶的簡(jiǎn)單的網(wǎng)格布局辫继,用來(lái)展示多行多列數(shù)據(jù)∷状龋可以通過下面屬性的配置來(lái)控制全局item的大小
//設(shè)置item行之間的最小間隔
@property (nonatomic) CGFloat minimumLineSpacing;
//設(shè)置item之間的最小間隔
@property (nonatomic) CGFloat minimumInteritemSpacing;
//設(shè)置item的大小
@property (nonatomic) CGSize itemSize;
//設(shè)置item大小的近似值姑宽,默認(rèn)是CGSizeZero(iOS8之后有效)
@property (nonatomic) CGSize estimatedItemSize NS_AVAILABLE_IOS(8_0); // defaults to CGSizeZero - setting a non-zero size enables cells that self-size via -preferredLayoutAttributesFittingAttributes:
//設(shè)置滾動(dòng)方向
@property (nonatomic) UICollectionViewScrollDirection scrollDirection; // default is UICollectionViewScrollDirectionVertical
//設(shè)置頭部引用視圖的大小,對(duì)于垂直滾動(dòng)時(shí)闺阱,寬不起作用炮车,高度起作用;水平滾動(dòng)相反
@property (nonatomic) CGSize headerReferenceSize;
////設(shè)置尾部引用視圖的大小
@property (nonatomic) CGSize footerReferenceSize;
//設(shè)置section的上下左右留白
@property (nonatomic) UIEdgeInsets sectionInset;
//下面兩個(gè)屬性在iOS9之后可用酣溃,用來(lái)設(shè)置是否粘貼頭部在屏幕的頭部和尾部在屏幕的尾部
@property (nonatomic) BOOL sectionHeadersPinToVisibleBounds NS_AVAILABLE_IOS(9_0);
@property (nonatomic) BOOL sectionFootersPinToVisibleBounds NS_AVAILABLE_IOS(9_0);
當(dāng)然也可以細(xì)致的配置每一個(gè)item大小瘦穆,這時(shí)需要實(shí)現(xiàn)UICollectionViewDelegateFlowLayout協(xié)議
//設(shè)置具體indexPath的item大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
//設(shè)置具體section的上下左右留白
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
//設(shè)置行最小間隔
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
//設(shè)置item間最小間隔
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
//設(shè)置頭部引用視圖的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
//設(shè)置尾部引用視圖的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
五、UICollectionViewLayout
UICollectionViewLayout是UICollectionView的精髓赊豌,是區(qū)別于UITableView的一個(gè)重要特征扛或,UICollectionView通過 UICollectionViewLayout 返回的 UICollectionViewLayoutAttributes 來(lái)布局每一個(gè)item。子類通過重寫UICollectionViewLayout中的方法可以實(shí)現(xiàn)各種各樣的布局樣式碘饼,也可以使用另外一套布局來(lái)更新當(dāng)前布局樣式熙兔,更可結(jié)合 UIDynamicBehavior 等UI動(dòng)力學(xué)完成各種各樣的酷炫效果腋腮,下面是UICollectionViewLayoutAttributes的頭文件內(nèi)容:
//設(shè)置item的frame
@property (nonatomic) CGRect frame;
//設(shè)置item的center
@property (nonatomic) CGPoint center;
//設(shè)置item的size
@property (nonatomic) CGSize size;
//設(shè)置item的transform3D
@property (nonatomic) CATransform3D transform3D;
//設(shè)置item的bounds
@property (nonatomic) CGRect bounds NS_AVAILABLE_IOS(7_0);
//設(shè)置item的transform
@property (nonatomic) CGAffineTransform transform NS_AVAILABLE_IOS(7_0);
//設(shè)置item的alpha
@property (nonatomic) CGFloat alpha;
//設(shè)置item的zIndex添吗,默認(rèn)是0和其他item在同一平面嫉到,設(shè)置小于0晶府,在其他item下面
@property (nonatomic) NSInteger zIndex; // default is 0
//設(shè)置item的hidden狀態(tài),通常為NO
@property (nonatomic, getter=isHidden) BOOL hidden;
//設(shè)置item的indexPath
@property (nonatomic, strong) NSIndexPath *indexPath;
//設(shè)置當(dāng)前元素的類別媒熊,是個(gè)美劇變量 cell/supplementaryView/decorationView
@property (nonatomic, readonly) UICollectionElementCategory representedElementCategory;
//展示的元素類型吞获,如果是cell 則為nil
@property (nonatomic, readonly, nullable) NSString *representedElementKind; // nil when representedElementCategory is UICollectionElementCategoryCell
//指定indexPath的cell的layoutAttributes
+ (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath;
//指定indexPath的supplementaryView的layoutAttributes
+ (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind withIndexPath:(NSIndexPath *)indexPath;
//指定indexPath的decorationView的layoutAttributes
+ (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind withIndexPath:(NSIndexPath *)indexPath;
下面是UICollectionViewLayout相關(guān)的API:
//構(gòu)造函數(shù)
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
//當(dāng)前l(fā)ayout服務(wù)的collectionView對(duì)象
@property (nullable, nonatomic, readonly) UICollectionView *collectionView;
//驗(yàn)證當(dāng)前l(fā)ayout角塑,會(huì)觸發(fā)collectionView的reloadData
- (void)invalidateLayout;
//驗(yàn)證當(dāng)前l(fā)ayout五慈,并且提供一個(gè)驗(yàn)證的上下文纳寂,也會(huì)觸發(fā)collectionView的reloadData
- (void)invalidateLayoutWithContext:(UICollectionViewLayoutInvalidationContext *)context NS_AVAILABLE_IOS(7_0);
//注冊(cè)decorationView用Class/nib
- (void)registerClass:(nullable Class)viewClass forDecorationViewOfKind:(NSString *)elementKind;
- (void)registerNib:(nullable UINib *)nib forDecorationViewOfKind:(NSString *)elementKind;
自定義layout需要關(guān)注的API:
//自定義layoutAttributesClass和invalidationContextClass在需要的時(shí)候
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) Class layoutAttributesClass; // override this method to provide a custom class to be used when instantiating instances of UICollectionViewLayoutAttributes
@property(class, nonatomic, readonly) Class invalidationContextClass NS_AVAILABLE_IOS(7_0); // override this method to provide a custom class to be used for invalidation contexts
#else
+ (Class)layoutAttributesClass; // override this method to provide a custom class to be used when instantiating instances of UICollectionViewLayoutAttributes
+ (Class)invalidationContextClass NS_AVAILABLE_IOS(7_0); // override this method to provide a custom class to be used for invalidation contexts
#endif
//UICollectionView在第一次layout的時(shí)候會(huì)調(diào)用prepareLayout,并且在當(dāng)前l(fā)ayout invalidated之后也會(huì)調(diào)用這個(gè)方法泻拦,子類需要重寫此方法完成相關(guān)配置
- (void)prepareLayout;
//UICollectionView會(huì)調(diào)用下面四個(gè)方法完成相關(guān)的配置信息
//返回給定rect內(nèi)的layoutAttributes數(shù)組
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
//返回給定indexPath的item的layoutAttributes
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
//返回給定indexPath的supplementaryView的layoutAttributes,如果有
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
//返回給定indexPath的decorationView的layoutAttributes忽媒,如果有
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath;
//是否驗(yàn)證給定的bounds争拐,會(huì)引起UICollectionView刷新layout
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
//返回給定bounds的無(wú)效上下文
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForBoundsChange:(CGRect)newBounds NS_AVAILABLE_IOS(7_0);
//是否驗(yàn)證layoutAttributes
- (BOOL)shouldInvalidateLayoutForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes NS_AVAILABLE_IOS(8_0);
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForPreferredLayoutAttributes:(UICollectionViewLayoutAttributes *)preferredAttributes withOriginalAttributes:(UICollectionViewLayoutAttributes *)originalAttributes NS_AVAILABLE_IOS(8_0);
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity; // return a point at which to rest after scrolling - for layouts that want snap-to-point scrolling behavior
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset NS_AVAILABLE_IOS(7_0); // a layout can return the content offset to be applied during transition or update animations
//返回collectionView的contentSize
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) CGSize collectionViewContentSize; // Subclasses must override this method and use it to return the width and height of the collection view’s content. These values represent the width and height of all the content, not just the content that is currently visible. The collection view uses this information to configure its own content size to facilitate scrolling.
#else
- (CGSize)collectionViewContentSize; // Subclasses must override this method and use it to return the width and height of the collection view’s content. These values represent the width and height of all the content, not just the content that is currently visible. The collection view uses this information to configure its own content size to facilitate scrolling.
#endif
刷新layout需要關(guān)注的 API:
- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;
- (void)finalizeCollectionViewUpdates; // called inside an animation block after the update
- (void)prepareForAnimatedBoundsChange:(CGRect)oldBounds; // UICollectionView calls this when its bounds have changed inside an animation block before displaying cells in its new bounds
- (void)finalizeAnimatedBoundsChange; // also called inside the animation block
// UICollectionView calls this when prior the layout transition animation on the incoming and outgoing layout
- (void)prepareForTransitionToLayout:(UICollectionViewLayout *)newLayout NS_AVAILABLE_IOS(7_0);
- (void)prepareForTransitionFromLayout:(UICollectionViewLayout *)oldLayout NS_AVAILABLE_IOS(7_0);
- (void)finalizeLayoutTransition NS_AVAILABLE_IOS(7_0); // called inside an animation block after the transition
// This set of methods is called when the collection view undergoes an animated transition such as a batch update block or an animated bounds change.
// For each element on screen before the invalidation, finalLayoutAttributesForDisappearingXXX will be called and an animation setup from what is on screen to those final attributes.
// For each element on screen after the invalidation, initialLayoutAttributesForAppearingXXX will be called and an animation setup from those initial attributes to what ends up on screen.
- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;
- (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;
// These methods are called by collection view during an update block.
// Return an array of index paths to indicate views that the layout is deleting or inserting in response to the update.
- (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);
排序需要關(guān)注的layout API:
- (NSIndexPath *)targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath withPosition:(CGPoint)position NS_AVAILABLE_IOS(9_0);
- (UICollectionViewLayoutAttributes *)layoutAttributesForInteractivelyMovingItemAtIndexPath:(NSIndexPath *)indexPath withTargetPosition:(CGPoint)position NS_AVAILABLE_IOS(9_0);
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForInteractivelyMovingItems:(NSArray<NSIndexPath *> *)targetIndexPaths withTargetPosition:(CGPoint)targetPosition previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths previousPosition:(CGPoint)previousPosition NS_AVAILABLE_IOS(9_0);
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:(NSArray<NSIndexPath *> *)indexPaths previousIndexPaths:(NSArray<NSIndexPath *> *)previousIndexPaths movementCancelled:(BOOL)movementCancelled NS_AVAILABLE_IOS(9_0);
六、UICollectionViewTransitionLayout
UICollectionViewTransitionLayout繼承自UICollectionViewLayout晦雨,用于切換當(dāng)前的layout架曹,提供過渡時(shí)期的layout
//UICollectionView過渡的進(jìn)度值
@property (assign, nonatomic) CGFloat transitionProgress;
//當(dāng)前UICollectionView的layout
@property (readonly, nonatomic) UICollectionViewLayout *currentLayout;
//切換之后的layout
@property (readonly, nonatomic) UICollectionViewLayout *nextLayout;
//初始化TransitionLayout對(duì)象
- (instancetype)initWithCurrentLayout:(UICollectionViewLayout *)currentLayout nextLayout:(UICollectionViewLayout *)newLayout NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
//下面的方法用于儲(chǔ)存過渡期LayoutAttributes的變化值
- (void)updateValue:(CGFloat)value forAnimatedKey:(NSString *)key;
- (CGFloat)valueForAnimatedKey:(NSString *)key;
結(jié)尾附上幾個(gè)常見的場(chǎng)景使用