前言
具體代碼demo如下:
GitHub_OC版本:Demo具體代碼
GitHub_Swift版本:Demo具體代碼
碼云 Demo具體代碼
更新日志
V2.4.0 - 增加對(duì)背景圖的點(diǎn)擊事件處理和控制,通過(guò)代理返回點(diǎn)擊的背景圖的IndexPath
V2.3.2 - 支持xib、storyboard 喚起,能夠默認(rèn)開(kāi)啟背景圖開(kāi)關(guān)設(shè)置
V2.3.0 - 新增對(duì)Cell的對(duì)齊模式進(jìn)行設(shè)置,支持(右對(duì)齊和首個(gè)Cell右側(cè)開(kāi)始)
V2.2.0 - 新增對(duì)Cell的對(duì)齊模式進(jìn)行設(shè)置,支持(右對(duì)齊)
V2.1.0 - 新增對(duì)Cell的對(duì)齊模式進(jìn)行設(shè)置,支持(居中對(duì)齊)
2020-01-13 更新版本到V2.0.0
2020-01-11 優(yōu)化代碼,對(duì)代碼邏輯進(jìn)行抽離,增加工具類等,新增支持Cell左對(duì)齊模式。
2019-12-16 更新支持根據(jù)section設(shè)置是否底色計(jì)算headeview、footerview。
2019-12-16 更新pod 1.1.0
??簡(jiǎn)單設(shè)計(jì)collectionview 底色和根據(jù)section不同設(shè)置不同顏色,支持collection橫豎樣式、自定義偏移量、投影。
??由于APP設(shè)計(jì)樣式的多樣性,很多時(shí)候我們需要用到一些特別的樣式,例如投影、圓角、某個(gè)空間下增加底色和投影等組合,這些看似很簡(jiǎn)單的樣式,其實(shí)也需要花不少時(shí)間進(jìn)行樣式的布局和調(diào)整等。
??例如本人遇到需要在collectionView,根據(jù)section不同設(shè)置不同的底色,需要?jiǎng)討B(tài)設(shè)置是否包含headerview,還需要設(shè)置投影等等,所以設(shè)計(jì)了這個(gè)可配置且動(dòng)態(tài)更新的 collection 背景顏色 控件??苫緷M足各種要求。
設(shè)計(jì)思路
1、繼承UICollectionViewFlowLayout,重寫(xiě)prepareLayout方法,在方法內(nèi)計(jì)算每個(gè)section的大小,并根據(jù)用戶設(shè)置的sectiooninset,進(jìn)行frame補(bǔ)充。
2、繼承UICollectionViewLayoutAttributes,增加底色、投影等參數(shù)。
3、在prepareLayout計(jì)算每個(gè)section的UICollectionViewLayoutAttributes并設(shè)置底色參數(shù),并進(jìn)行保存,
4、在layoutAttributesForElementsInRect進(jìn)行rect判斷獲取attr。
5、在applyLayoutAttributes內(nèi)機(jī)進(jìn)行樣式設(shè)置。
效果圖:

支持類型:
1、collectionView section底色。
2、是否包含headerview。
3、是否包含footerview。
4、支持borderWidth、borderColor。
5、支持shadow投影。
6、支持collectionView,Vertical,Horizontal。
7、支持根據(jù)不同section分別設(shè)置不同底色顯示。
8、支持根據(jù)section單獨(dú)判斷是否計(jì)算對(duì)應(yīng)headerview和footerview
9、新增對(duì)Cell的對(duì)齊模式進(jìn)行設(shè)置,支持(左、中、右對(duì)齊),支持右對(duì)齊后右邊開(kāi)始排列。
10、支持底色點(diǎn)擊,點(diǎn)擊后通過(guò)delegate回調(diào) --- V2.4.0
核心代碼
/// 計(jì)算默認(rèn)不包含headerview和footerview的背景大小
/// @paramframeframe description
/// @paramsectionInsetsectionInset description
- (CGRect)calculateDefaultFrameWithSectionFrame:(CGRect)frame sectionInset:(UIEdgeInsets)sectionInset{
CGRectsectionFrame = frame;
sectionFrame.origin.x-= sectionInset.left;
sectionFrame.origin.y-= sectionInset.top;
if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
sectionFrame.size.width+= sectionInset.left+ sectionInset.right;
//減去系統(tǒng)adjustInset的top
if(@available(iOS11.0, *)) {
sectionFrame.size.height = self.collectionView.frame.size.height - self.collectionView.adjustedContentInset.top;
}else{
sectionFrame.size.height = self.collectionView.frame.size.height - fabs(self.collectionView.contentOffset.y)/*適配iOS11以下*/;
}
}else{
sectionFrame.size.width = self.collectionView.frame.size.width;
sectionFrame.size.height+= sectionInset.top+ sectionInset.bottom;
}
returnsectionFrame;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
NSMutableArray * attrs = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
//用戶設(shè)置了對(duì)稱方式,進(jìn)行對(duì)稱設(shè)置 (若沒(méi)設(shè)置,不執(zhí)行,繼續(xù)其他計(jì)算)
if (self.collectionCellAlignmentType != JJCollectionViewFlowLayoutAlignmentTypeBySystem
&& self.scrollDirection == UICollectionViewScrollDirectionVertical) {
//豎向,Cell對(duì)齊方式暫不支持橫向
NSArray *formatGroudAttr = [self groupLayoutAttributesForElementsByYLineWithLayoutAttributesAttrs:attrs];
[self evaluatedAllCellSettingFrameWithLayoutAttributesAttrs:formatGroudAttr
toChangeAttributesAttrsList:&attrs
cellAlignmentType:self.collectionCellAlignmentType];
}
for (UICollectionViewLayoutAttributes *attr in self.decorationViewAttrs) {
[attrs addObject:attr];
}
return attrs;
}
- (void)prepareLayout{
[super prepareLayout];
//判斷是否手動(dòng)關(guān)閉了計(jì)算,默認(rèn)開(kāi)啟(如只想使用對(duì)齊方式、可強(qiáng)制進(jìn)行強(qiáng)制關(guān)閉,計(jì)算方法可不走)
if (!self.isRoundEnabled) {
return;
}
NSInteger sections = [self.collectionView numberOfSections];
id <JJCollectionViewDelegateRoundFlowLayout> delegate = (id <JJCollectionViewDelegateRoundFlowLayout>)self.collectionView.delegate;
//檢測(cè)是否實(shí)現(xiàn)了背景樣式模塊代理
if (![delegate respondsToSelector:@selector(collectionView:layout:configModelForSectionAtIndex:)]) {
return;
}
//1.初始化
[self registerClass:[JJCollectionReusableView class] forDecorationViewOfKind:JJCollectionViewRoundSection];
[self.decorationViewAttrs removeAllObjects];
for (NSInteger section = 0; section < sections; section++) {
...(計(jì)算內(nèi)容)
}
如何使用:
集成方法:
pod?'JJCollectionViewRoundFlowLayout'
1、底色相關(guān)設(shè)置
背景底色設(shè)置(Header、Footer、Cell區(qū)域)
//可選設(shè)置
@property (assign, nonatomic)BOOLisCalculateHeader;//是否計(jì)算header
@property (assign, nonatomic)BOOLisCalculateFooter;//是否計(jì)算footer
/// 設(shè)置底色參數(shù)
/// @param collectionView collectionView description
/// @param collectionViewLayout collectionViewLayout description
/// @param section section description
- (JJCollectionViewRoundConfigModel *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout configModelForSectionAtIndex:(NSInteger)section;
/// 設(shè)置底色偏移點(diǎn)量(與collectionview的sectionInset用法相同,但是與sectionInset區(qū)分)
/// @param collectionView collectionView description
/// @param collectionViewLayout collectionViewLayout description
/// @param section section description
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout borderEdgeInsertsForSectionAtIndex:(NSInteger)section;
/// 設(shè)置是否計(jì)算headerview(根據(jù)section判斷是否單獨(dú)計(jì)算)
/// @param collectionView collectionView description
/// @param collectionViewLayout collectionViewLayout description
/// @param section section description
- (BOOL)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout isCalculateHeaderViewIndex:(NSInteger)section;
/// 設(shè)置是否計(jì)算footerview(根據(jù)section判斷是否單獨(dú)計(jì)算)
/// @param collectionView collectionView description
/// @param collectionViewLayout collectionViewLayout description
/// @param section section description
- (BOOL)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout isCalculateFooterViewIndex:(NSInteger)section;
//初始化
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc]init];
UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) collectionViewLayout:layout];
collectionView.delegate = self;
collectionView.dataSource = self;
#在collectionview頁(yè)面代碼上加入代理(JJCollectionViewDelegateRoundFlowLayout)
并實(shí)現(xiàn)如下兩個(gè)方法:
#pragma mark - JJCollectionViewDelegateRoundFlowLayout
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout borderEdgeInsertsForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(5.f, 12, 5, 12);
}
- (JJCollectionViewRoundConfigModel *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout configModelForSectionAtIndex:(NSInteger)section{
JJCollectionViewRoundConfigModel *model = [[JJCollectionViewRoundConfigModel alloc]init];
model.backgroundColor = [UIColor colorWithRed:233/255.0 green:233/255.0 blue:233/255.0 alpha:1.0];
model.cornerRadius = 10;
return model;
}
效果如下:

2、對(duì)齊方式相關(guān)
Cell(左對(duì)齊、居中對(duì)齊、右對(duì)齊、右對(duì)齊且右測(cè)開(kāi)始排列)
//創(chuàng)建Layout,設(shè)置layout對(duì)齊方式,
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc]init];
layout.collectionCellAlignmentType = JJCollectionViewFlowLayoutAlignmentTypeByLeft;
/*
JJCollectionViewFlowLayoutAlignmentTypeBySystem = 0,//不設(shè)置
JJCollectionViewFlowLayoutAlignmentTypeByLeft, //左對(duì)齊
JJCollectionViewFlowLayoutAlignmentTypeByCenter, //居中
JJCollectionViewFlowLayoutAlignmentTypeByRight, // 右對(duì)齊
JJCollectionViewFlowLayoutAlignmentTypeByRightAndStartR //右對(duì)齊且右開(kāi)始排序
*/
效果如下:

3、背景點(diǎn)擊相關(guān)
點(diǎn)擊背景反饋
/// 背景圖點(diǎn)擊事件
/// @param collectionView collectionView description
/// @param indexPath 點(diǎn)擊背景圖的indexPath
- (void)collectionView:(UICollectionView *)collectionView didSelectDecorationViewAtIndexPath:(NSIndexPath *)indexPath;
//初始化
JJCollectionViewRoundFlowLayout *layout = [[JJCollectionViewRoundFlowLayout alloc]init];
UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) collectionViewLayout:layout];
collectionView.delegate = self;
collectionView.dataSource = self;
#在collectionview頁(yè)面代碼上加入代理(JJCollectionViewDelegateRoundFlowLayout)
并實(shí)現(xiàn)如下方法:
#pragma mark - JJCollectionViewDelegateRoundFlowLayout
- (void)collectionView:(UICollectionView *)collectionView didSelectDecorationViewAtIndexPath:(nonnull NSIndexPath *)indexPath {
NSString *message = [NSString stringWithFormat:@"section --- %ld \n row --- %ld",indexPath.section,indexPath.row];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"JJCollectionViewRoundFlowLayout"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
}
效果如下:

具體代碼demo如下:
GitHub Demo具體代碼
碼云 Demo具體代碼
大家有空可star。
后續(xù)可能會(huì)單獨(dú)更新swift版本,敬請(qǐng)期待。
如有問(wèn)題,可以直接提issues,或者發(fā)送郵件到kingjiajie@sina.com,或者直接回復(fù)。謝謝。