因?yàn)閁ICollectionViewCompositionalLayout,再次愛上UICollectionView。
最近在做橫向滾動(dòng)的UICollectionView的時(shí)候,cell不是全屏的,又想實(shí)現(xiàn)按cell分頁(yè)效果而不是按屏幕寬度分頁(yè),我注意到AppStore的游戲和App tab頁(yè)面橫向滾動(dòng)的效果非常棒,在搜索過程中發(fā)現(xiàn)了UICollectionViewCompositionalLayout關(guān)鍵字,遂把玩之。(UICollectionViewCompositionalLayout在WWDC2019就推出的,然而我并沒有看WWDC,也不是第一時(shí)間更新到最新系統(tǒng)去吃螃蟹者,寫到這里其實(shí)內(nèi)心有點(diǎn)慚愧??)
至于怎么在iOS13以下實(shí)現(xiàn)按cell分頁(yè)效果的,感興趣的可以看上篇:Paging UICollectionView by smaller cells, not screen
UICollectionViewCompositionalLayout是蘋果在iOS13推出的一個(gè)高度自適應(yīng)和靈活的布局對(duì)象,它是UICollectionView的一種布局方式,它的設(shè)計(jì)是可組合的、靈活的和快速的。
我們先看下iOS13上AppStore上的頁(yè)面效果,嵌套交叉滾動(dòng),算是正常的需求了,如果要我們做,我們肯定是用類似cell上嵌套UICollectionView的思路來實(shí)現(xiàn),我們不僅要寫縱向的cell樣式、橫向的cell樣式,還要處理嵌套cell的點(diǎn)擊事件,簡(jiǎn)直是太繁瑣了。
現(xiàn)在,有了UICollectionViewCompositionalLayout這把金剛鉆,整個(gè)頁(yè)面我們使用一個(gè)UICollectionView即可實(shí)現(xiàn),在我們配置好UICollectionViewCompositionalLayout布局樣式后,剩下的,放眼望去,滿屏皆是這一個(gè)UICollectionView的cell,是不是很簡(jiǎn)單?(蘋果公司終于考慮到了這一點(diǎn),然而啥時(shí)候才能最低支持iOS13?)
下面來結(jié)合demo一起解開UICollectionViewCompositionalLayout的神秘面紗。
主要概念

由圖可見,層級(jí)關(guān)系為 NSCollectionLayoutItem -> NSCollectionLayoutGroup -> NSCollectionLayoutSection
其中:
NSCollectionLayoutDimension 維度尺寸
用來創(chuàng)建NSCollectionLayoutSize,有按占group的比例創(chuàng)建尺寸fractionalWidthDimension:、fractionalHeightDimension:,按固定值創(chuàng)建尺寸absoluteDimension:、按預(yù)估值創(chuàng)建尺寸estimatedDimension:的方法。NSCollectionLayoutSize 布局尺寸
NSCollectionLayoutItem和NSCollectionLayoutGroup在初始化時(shí)都需要通過其指定尺寸NSCollectionLayoutItem 布局單元
可以配置尺寸、裝飾視圖NSCollectionLayoutGroup 分組
是NSCollectionLayoutItem的子類,支持橫向、縱向、自定義分組。注意interItemSpacing屬性只對(duì)NSCollectionLayoutGroup創(chuàng)建時(shí)指定了多個(gè)item的才有效。NSCollectionLayoutSection 分區(qū)
與group綁定,可以通過boundarySupplementaryItems制定組頭組尾、通過visibleItemsInvalidationHandler監(jiān)聽滾動(dòng),通過orthogonalScrollingBehavior設(shè)置在交叉軸上如何滾動(dòng)與分頁(yè)。UICollectionViewCompositionalLayout 組合布局
與NSCollectionLayoutSection綁定,initWithSectionProvider方可以滿足為UICollectionView的每個(gè)Section配置不同的NSCollectionLayoutSection。
NSCollectionLayoutItem的對(duì)齊方式

首先,這里創(chuàng)建了一個(gè)group,包含一大一小不同的item,我們想讓小的item水平垂直居中,主要用到了item的edgeSpacing屬性,這里使用NSCollectionLayoutSpacing創(chuàng)建了一個(gè)距離邊界都保持相同的靈活間距。這里注意一點(diǎn),這里創(chuàng)建group時(shí)指定了多個(gè)item,所以設(shè)置interItemSpacing屬性才有效果,如果只指定了一個(gè)item,該屬性不起效。
//大item 寬占group的一半,高占滿group
NSCollectionLayoutSize *itemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:0.5] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0]];
NSCollectionLayoutItem *item = [NSCollectionLayoutItem itemWithLayoutSize:itemSize];
//小item 寬占group的四分之一,高占group的一半
NSCollectionLayoutSize *itemSize1 = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:0.25] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:0.5]];
NSCollectionLayoutItem *item1 = [NSCollectionLayoutItem itemWithLayoutSize:itemSize1];
item1.contentInsets = NSDirectionalEdgeInsetsMake(20, 20, 20, 20);//內(nèi)邊距 會(huì)改變其size
//item1.edgeSpacing = [NSCollectionLayoutEdgeSpacing spacingForLeading:nil top:[NSCollectionLayoutSpacing flexibleSpacing:10] trailing:nil bottom:nil];//外邊距,值可能會(huì)被優(yōu)化 【相對(duì)于group底部對(duì)齊】
item1.edgeSpacing = [NSCollectionLayoutEdgeSpacing spacingForLeading:[NSCollectionLayoutSpacing flexibleSpacing:10] top:[NSCollectionLayoutSpacing flexibleSpacing:10] trailing:[NSCollectionLayoutSpacing flexibleSpacing:10] bottom:[NSCollectionLayoutSpacing flexibleSpacing:10]];//【相對(duì)于group居中對(duì)齊】
//一個(gè)group可以指定多個(gè)item,指定多個(gè),對(duì)應(yīng)的cell會(huì)按items的樣式依次布局
NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalWidthDimension:0.25]];
NSCollectionLayoutGroup *group = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:groupSize subitems:@[item, item1]];
//interItemSpacing對(duì)指定了多個(gè)subitems才有效
group.interItemSpacing = [NSCollectionLayoutSpacing fixedSpacing:5];
//一個(gè)section只能指定一個(gè)group
NSCollectionLayoutSection *section = [NSCollectionLayoutSection sectionWithGroup:group];
section.contentInsets = NSDirectionalEdgeInsetsFromString(@"{5.0, 5.0, 5.0, 5.0}");
//layout只能指定一個(gè)section
UICollectionViewCompositionalLayout *layout = [[UICollectionViewCompositionalLayout alloc]initWithSection:section configuration:config];
組合group、組頭組尾、補(bǔ)充視圖

由于NSCollectionLayoutGroup繼承自NSCollectionLayoutItem,在創(chuàng)建NSCollectionLayoutGroup時(shí)需要指定NSCollectionLayoutItem,所以,我們就可以把group和item進(jìn)行組合來組合出一個(gè)新的group。
可以通過下面的方式創(chuàng)建組頭組尾以及補(bǔ)充視圖:
//配置裝飾Badge
//裝飾視圖中心點(diǎn)等于cell的右上角頂點(diǎn)
NSCollectionLayoutAnchor *badgeAnchor = [NSCollectionLayoutAnchor layoutAnchorWithEdges:NSDirectionalRectEdgeTop|NSDirectionalRectEdgeTrailing fractionalOffset:CGPointMake(0.5, -0.5)];
NSCollectionLayoutSize *badgeSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension absoluteDimension:20] heightDimension:[NSCollectionLayoutDimension absoluteDimension:20]];
NSCollectionLayoutSupplementaryItem *badge = [NSCollectionLayoutSupplementaryItem supplementaryItemWithLayoutSize:badgeSize elementKind:@"Badge" containerAnchor:badgeAnchor];
//頂部大item
NSCollectionLayoutSize *topItemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalWidthDimension:9.0/16.0]];
NSCollectionLayoutItem *topItem = [NSCollectionLayoutItem itemWithLayoutSize:topItemSize];
//底部小item 通過supplementaryItems屬性指定裝飾badge視圖
NSCollectionLayoutSize *bottomItemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:0.5] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0]];
NSCollectionLayoutItem *bottomItem = [NSCollectionLayoutItem itemWithLayoutSize:bottomItemSize supplementaryItems:@[badge]];
bottomItem.contentInsets = NSDirectionalEdgeInsetsMake(8, 8, 8, 8);
//底部放兩個(gè)小item對(duì)應(yīng)的group
NSCollectionLayoutSize *bottomGroupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalWidthDimension:0.5]];
//注意:該api放兩個(gè)相同的item是不起效的
//NSCollectionLayoutGroup *bottomGroup = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:bottomGroupSize subitems:@[bottomItem, bottomItem]];
////會(huì)在這個(gè)分組中放入兩個(gè)相同的item。并且這里設(shè)置了2,即使bottomItemSize width設(shè)置比較大,依然會(huì)平分
NSCollectionLayoutGroup *bottomGroup = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:bottomGroupSize subitem:bottomItem count:2];
//組合group ???? 注意這里的尺寸一點(diǎn)要是組合的大小
NSCollectionLayoutSize *fullGroupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalWidthDimension:9.0/16.0 + 0.5]];
NSCollectionLayoutGroup *nestedGroup = [NSCollectionLayoutGroup verticalGroupWithLayoutSize:fullGroupSize subitems:@[topItem, bottomGroup]];
//雖然一個(gè)section只能指定一個(gè)group,但可以group中可以組合item和其他group
NSCollectionLayoutSection *section = [NSCollectionLayoutSection sectionWithGroup:nestedGroup];
NSCollectionLayoutSize *headerSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension estimatedDimension:44]];
NSCollectionLayoutBoundarySupplementaryItem *headerItem = [NSCollectionLayoutBoundarySupplementaryItem boundarySupplementaryItemWithLayoutSize:headerSize elementKind:UICollectionElementKindSectionHeader alignment:NSRectAlignmentTop];
//是否懸停
//headerItem.pinToVisibleBounds = YES;
//配置組頭組尾
NSCollectionLayoutSize *footerSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension estimatedDimension:60]];
NSCollectionLayoutBoundarySupplementaryItem *footerItem = [NSCollectionLayoutBoundarySupplementaryItem boundarySupplementaryItemWithLayoutSize:footerSize elementKind:UICollectionElementKindSectionFooter alignment:NSRectAlignmentBottom];
//給section的boundarySupplementaryItems屬性賦值
section.boundarySupplementaryItems = @[headerItem, footerItem];
通過這個(gè)demo,我們還可以看出UICollectionView的numberOfSections和NSCollectionLayoutSection的關(guān)系。這里我第一個(gè)分區(qū)的numberOfSections=2,numberOfRows=8,每個(gè)NSCollectionLayoutSection可以放下三個(gè)cell,實(shí)際效果是會(huì)按這個(gè)NSCollectionLayoutSection樣式依次布局cell,但每個(gè)numberOfSections對(duì)應(yīng)的分區(qū)開始的時(shí)候一定是從一個(gè)新的NSCollectionLayoutSection布局開始的,我們看下兩個(gè)分區(qū)的交界處即可理解:

用裝飾視圖做背景,實(shí)現(xiàn)類似UITableViewStyleGrouped樣式

//group加裝飾背景
1.創(chuàng)建NSCollectionLayoutDecorationItem 它是NSCollectionLayoutItem的子類,不能指定layoutSize。
2.給NSCollectionLayoutSection的decorationItems賦值。
3.在UICollectionViewCompositionalLayout上面注冊(cè)decorationView,在這里注冊(cè)的類實(shí)現(xiàn)樣式的自定義。
注意:不是在collectionview上注冊(cè)SupplementaryView。
NSCollectionLayoutSize *itemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0]];
NSCollectionLayoutItem *item = [NSCollectionLayoutItem itemWithLayoutSize:itemSize];
NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension absoluteDimension:44]];
NSCollectionLayoutGroup *group = [NSCollectionLayoutGroup verticalGroupWithLayoutSize:groupSize subitems:@[item]];
NSCollectionLayoutSection *section = [NSCollectionLayoutSection sectionWithGroup:group];
section.contentInsets = NSDirectionalEdgeInsetsMake(20, 20, 20, 20);
NSCollectionLayoutDecorationItem *backItem = [NSCollectionLayoutDecorationItem backgroundDecorationItemWithElementKind:@"background"];
backItem.contentInsets = NSDirectionalEdgeInsetsMake(10, 10, 10, 10);
section.decorationItems = @[backItem];
UICollectionViewCompositionalLayoutConfiguration *config = [UICollectionViewCompositionalLayoutConfiguration new];
config.interSectionSpacing = 20;//不同section之間的間距
UICollectionViewCompositionalLayout *layout = [[UICollectionViewCompositionalLayout alloc]initWithSection:section configuration:config];
[layout registerClass:[MyDecorateView class] forDecorationViewOfKind:@"background"];
自定義NSCollectionLayoutGroup
上面的demo都是水平或垂直的group樣式,系統(tǒng)也提供了自定義group樣式的api,這里只是簡(jiǎn)單舉個(gè)例子。

NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension absoluteDimension:200]];
CGFloat width = [UIScreen mainScreen].bounds.size.width/3.0;
CGFloat height = 200/3.0;
//無法橫向滾動(dòng)
NSCollectionLayoutGroup *group = [NSCollectionLayoutGroup customGroupWithLayoutSize:groupSize itemProvider:^NSArray<NSCollectionLayoutGroupCustomItem *> * _Nonnull(id<NSCollectionLayoutEnvironment> _Nonnull layoutEnvironment) {
//UICollectionView的每個(gè)section走一次
//這里想象空間很大,自己愛咋放咋放
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:8];
CGFloat x = 0 , y = 0;
for(NSInteger i = 0; i < 8; i++){
NSCollectionLayoutGroupCustomItem *customItem = [NSCollectionLayoutGroupCustomItem customItemWithFrame:CGRectMake(x, y, width, height) zIndex:1000+i];
[arr addObject:customItem];
x += width;
if(i > 0 && i % 3 == 0){
x = 0;
y += height;
}
}
return arr.copy;
}];
綜合實(shí)現(xiàn)類似AppStore tab頁(yè)的效果
結(jié)合上面的例子,同時(shí)再實(shí)現(xiàn)為UICollectionView的每個(gè)分區(qū)都單獨(dú)配置一個(gè)不同的section樣式來實(shí)現(xiàn)目標(biāo)效果。

其中知識(shí)點(diǎn):
如何監(jiān)測(cè)橫向滾動(dòng)的group當(dāng)前滾動(dòng)到了哪個(gè)cell?
section的visibleItemsInvalidationHandler屬性正交軸上滾動(dòng)模式
UICollectionLayoutSectionOrthogonalScrollingBehaviorContinuous 正常連續(xù)滾動(dòng)
UICollectionLayoutSectionOrthogonalScrollingBehaviorPaging 正常分頁(yè)輪播(頁(yè)寬等于UICollectionView的寬度)
UICollectionLayoutSectionOrthogonalScrollingBehaviorContinuousGroupLeadingBoundary 停止?jié)L動(dòng)時(shí)一定會(huì)停留在group的邊界處
UICollectionLayoutSectionOrthogonalScrollingBehaviorGroupPaging 按group的尺寸進(jìn)行分頁(yè)
UICollectionLayoutSectionOrthogonalScrollingBehaviorGroupPagingCentered 也是按group的尺寸進(jìn)行分頁(yè),但會(huì)沿正交軸增加首尾間距讓group居中
UICollectionViewCompositionalLayoutConfiguration *config = [UICollectionViewCompositionalLayoutConfiguration new];
config.interSectionSpacing = 30;//不同section之間的間距
UICollectionViewCompositionalLayout *layout = [[UICollectionViewCompositionalLayout alloc]initWithSectionProvider:^NSCollectionLayoutSection * _Nullable(NSInteger section, id<NSCollectionLayoutEnvironment> environment) {
return [self generateSectionForSection:section];
}];
layout.configuration = config;
- (NSCollectionLayoutSection *)generateSectionForSection:(NSInteger)section
{
NSCollectionLayoutGroup *group;
NSDirectionalEdgeInsets sectionInsets = NSDirectionalEdgeInsetsMake(0, 0, 0, 0);
UICollectionLayoutSectionOrthogonalScrollingBehavior behavior = UICollectionLayoutSectionOrthogonalScrollingBehaviorContinuous;
switch (section) {
case 0:
case 5:
{
//頂部banner item
//效果:paging by cell 看起來cell距離屏幕左右各20像素
sectionInsets = NSDirectionalEdgeInsetsMake(0, 15, 0, 15);
behavior = UICollectionLayoutSectionOrthogonalScrollingBehaviorGroupPaging;//完美的paging by cell效果
CGFloat bannerSize = [UIScreen mainScreen].bounds.size.width - 30;//原本占screenwidth-30
NSCollectionLayoutSize *bannerItemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0]];
NSCollectionLayoutItem *bannerItem = [NSCollectionLayoutItem itemWithLayoutSize:bannerItemSize];
bannerItem.contentInsets = NSDirectionalEdgeInsetsMake(0, 5, 0, 5);//左右各收縮5像素 占screenwidth-40
NSCollectionLayoutSize *bannerGroupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension absoluteDimension:bannerSize] heightDimension:[NSCollectionLayoutDimension absoluteDimension:bannerSize]];
group = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:bannerGroupSize subitem:bannerItem count:1];//水平
break;
}
case 1:
case 2:
case 4:
case 7:
case 9:
case 10:
{
//每列三行的cell樣式
sectionInsets = NSDirectionalEdgeInsetsMake(0, 15, 0, 15);
behavior = UICollectionLayoutSectionOrthogonalScrollingBehaviorGroupPaging;//完美的paging by cell效果
CGFloat oneThirdWidth = [UIScreen mainScreen].bounds.size.width - 30;
CGFloat oneThirdHeight = 80;
NSCollectionLayoutSize *oneThirdItemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0/3.0]];
NSCollectionLayoutItem *oneThirdItem = [NSCollectionLayoutItem itemWithLayoutSize:oneThirdItemSize];
oneThirdItem.contentInsets = NSDirectionalEdgeInsetsMake(0, 5, 0, 5);
NSCollectionLayoutSize *oneThirdGroupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension absoluteDimension:oneThirdWidth] heightDimension:[NSCollectionLayoutDimension absoluteDimension:oneThirdHeight * 3.0]];
group = [NSCollectionLayoutGroup verticalGroupWithLayoutSize:oneThirdGroupSize subitem:oneThirdItem count:3];//垂直
break;
}
case 3:
{
//今天看什么banner
sectionInsets = NSDirectionalEdgeInsetsMake(0, 15, 0, 15);
behavior = UICollectionLayoutSectionOrthogonalScrollingBehaviorGroupPaging;//完美的paging by cell效果
CGFloat bannerWidth = [UIScreen mainScreen].bounds.size.width - 150;
CGFloat bannerHeight = 180;
NSCollectionLayoutSize *bannerItemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0]];
NSCollectionLayoutItem *bannerItem = [NSCollectionLayoutItem itemWithLayoutSize:bannerItemSize];
bannerItem.contentInsets = NSDirectionalEdgeInsetsMake(0, 5, 0, 5);
NSCollectionLayoutSize *bannerGroupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension absoluteDimension:bannerWidth] heightDimension:[NSCollectionLayoutDimension absoluteDimension:bannerHeight]];
group = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:bannerGroupSize subitem:bannerItem count:1];//水平
break;
}
case 6:
{
//熱門類別
sectionInsets = NSDirectionalEdgeInsetsMake(0, 20, 0, 20);
CGFloat cellWidth = [UIScreen mainScreen].bounds.size.width - 40;
CGFloat cellHeight = 50;
NSCollectionLayoutSize *itemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0]];
NSCollectionLayoutItem *item = [NSCollectionLayoutItem itemWithLayoutSize:itemSize];
NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension absoluteDimension:cellWidth] heightDimension:[NSCollectionLayoutDimension absoluteDimension:cellHeight * 8]];
group = [NSCollectionLayoutGroup verticalGroupWithLayoutSize:groupSize subitem:item count:8];//垂直
break;
}
case 8:
{
//每列兩行的cell樣式
sectionInsets = NSDirectionalEdgeInsetsMake(0, 15, 0, 15);
behavior = UICollectionLayoutSectionOrthogonalScrollingBehaviorGroupPaging;//完美的paging by cell效果
CGFloat oneSecondWidth = [UIScreen mainScreen].bounds.size.width - 30;
CGFloat oneSecondHeight = 120;
NSCollectionLayoutSize *oneSecondItemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0/2.0]];
NSCollectionLayoutItem *oneSecondItem = [NSCollectionLayoutItem itemWithLayoutSize:oneSecondItemSize];
oneSecondItem.contentInsets = NSDirectionalEdgeInsetsMake(0, 5, 0, 5);
NSCollectionLayoutSize *oneSecondGroupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension absoluteDimension:oneSecondWidth] heightDimension:[NSCollectionLayoutDimension absoluteDimension:oneSecondHeight * 2.0]];
group = [NSCollectionLayoutGroup verticalGroupWithLayoutSize:oneSecondGroupSize subitem:oneSecondItem count:2];//垂直
break;
}
case 11:
{
//快速鏈接
sectionInsets = NSDirectionalEdgeInsetsMake(0, 20, 0, 20);
CGFloat cellWidth = [UIScreen mainScreen].bounds.size.width - 40;
CGFloat cellHeight = 50;
NSCollectionLayoutSize *itemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1.0]];
NSCollectionLayoutItem *item = [NSCollectionLayoutItem itemWithLayoutSize:itemSize];
NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension absoluteDimension:cellWidth] heightDimension:[NSCollectionLayoutDimension absoluteDimension:cellHeight * 8]];
group = [NSCollectionLayoutGroup verticalGroupWithLayoutSize:groupSize subitem:item count:8];//垂直
break;
break;
}
}
NSCollectionLayoutSection *layoutSection = [NSCollectionLayoutSection sectionWithGroup:group];
layoutSection.orthogonalScrollingBehavior = behavior;
layoutSection.contentInsets = sectionInsets;
if(section == 0){
layoutSection.visibleItemsInvalidationHandler = ^(NSArray<id<NSCollectionLayoutVisibleItem>> * _Nonnull visibleItems, CGPoint contentOffset, id<NSCollectionLayoutEnvironment> _Nonnull layoutEnvironment) {
//這里可以判斷哪個(gè)cell滾動(dòng)到了屏幕中心
};
}
//配置組頭組尾
NSCollectionLayoutSize *headerSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1.0] heightDimension:[NSCollectionLayoutDimension estimatedDimension:44]];
NSCollectionLayoutBoundarySupplementaryItem *headerItem = [NSCollectionLayoutBoundarySupplementaryItem boundarySupplementaryItemWithLayoutSize:headerSize elementKind:UICollectionElementKindSectionHeader alignment:NSRectAlignmentTop];
layoutSection.boundarySupplementaryItems = @[headerItem];
return layoutSection;
}
總結(jié)
UICollectionViewCompositionalLayout是繼UICollectionViewFlowLayout之后,蘋果公司為開發(fā)者提供的一個(gè)更加靈活功能更加強(qiáng)大的一種布局方案。這是順應(yīng)時(shí)代的產(chǎn)物,是iOS開發(fā)者的開發(fā)利器,可以很大程度上提升開發(fā)效率,用更少的時(shí)間完成更復(fù)雜的布局效果。??除了API越來與長(zhǎng)外,其他沒什么毛病??。
源碼已放至Github: ATPagingByCell