前言
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView
@available(iOS 6.0, *) public class UICollectionView : UIScrollView
1、collectionView 的创建
-
Objective-C
-
ViewController.m
- 遵守协议 UICollectionViewDataSource, UICollectionViewDelegate
// 数据源初始化 // 声明数据源 @property(nonatomic, retain)NSMutableArray *myDataArray; myDataArray = [[NSMutableArray alloc] init]; NSMutableArray *titleNameArray = [[NSMutableArray alloc] init]; NSMutableArray *imageNameArray = [[NSMutableArray alloc] init]; for (int i = 1; i <= 15; i++) { [titleNameArray addObject:[NSString stringWithFormat:@"第 %i 个", i]]; [imageNameArray addObject:[NSString stringWithFormat:@"2_%i", i]]; } [myDataArray addObject:titleNameArray]; [myDataArray addObject:imageNameArray]; // 网格视图初始化 // 创建网格视图布局对象,可以设置滑动方向,cell 的间距等 UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; // 创建网格视图对象,必须有布局对象 UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height - 20) collectionViewLayout:flowLayout]; // 设置代理 collectionView.dataSource = self; collectionView.delegate = self; // 将网格视图添加到屏幕视图 [self.view addSubview:collectionView]; // 注册自定义表格视图 [collectionView registerClass:[myCollectionViewCell1 class] forCellWithReuseIdentifier:@"myCell"]; // UICollectionView 协议方法 // 设置网格数 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return [[myDataArray objectAtIndex:0] count]; } // 设置网格大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *) indexPath { return CGSizeMake((self.view.bounds.size.width - 40) / 3, 170); } // 设置每个网格的内容 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // 使用自定义 Cell 创建,cell 必须用注册的方式定义 myCollectionViewCell1 *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"myCell" forIndexPath:indexPath]; // 设置 Cell 中视图包含的内容 cell.nameLabel.text = [myDataArray[0] objectAtIndex:indexPath.item]; cell.iconImageView.image = [UIImage imageNamed:[myDataArray[1] objectAtIndex:indexPath.item]]; return cell; }
-
myCollectionViewCell.h
@interface myCollectionViewCell1 : UICollectionViewCell @property(nonatomic, retain)UILabel *nameLabel; @property(nonatomic, retain)UIImageView *iconImageView; @end
-
myCollectionViewCell.m
- (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 创建标签视图 _nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, 20)]; _nameLabel.backgroundColor = [UIColor orangeColor]; _nameLabel.textAlignment = NSTextAlignmentCenter; [self.contentView addSubview:_nameLabel]; // 创建图片视图 _iconImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, self.bounds.size.width, self.bounds.size.height - 20)]; [self.contentView addSubview:_iconImageView]; } return self; }
-
-
Swift
-
ViewController.swift
- 遵守协议 UICollectionViewDataSource, UICollectionViewDelegate
// 数据源初始化 // 声明数据源 var dataArray:[[String]] = Array() var titleNameArray:[String] = Array() var imageNameArray:[String] = Array() for i in 1...15 { titleNameArray.append("第 \(i) 个") imageNameArray.append("2_\(i)") } dataArray.append(titleNameArray) dataArray.append(imageNameArray) // 网格视图初始化 // 创建网格视图布局对象,可以设置滑动方向,cell 的间距等 let flowLayout = UICollectionViewFlowLayout() // 创建网格视图对象,必须有布局对象 let collectionView = UICollectionView(frame: CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height - 20), collectionViewLayout: flowLayout) // 设置代理 collectionView.dataSource = self collectionView.delegate = self // 将网格视图添加到屏幕视图 self.view.addSubview(collectionView) // 注册自定义表格视图 collectionView.registerClass(myCollectionViewCell1.self, forCellWithReuseIdentifier: "myCell") // UICollectionView 协议方法 // 设置网格数 func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return dataArray[0].count } // 设置网格大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize{ return CGSizeMake((self.view.bounds.size.width - 40) / 3, 170) } // 设置每个网格的内容,cell 必须用注册方式定义 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { // 使用自定义 Cell 创建 let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! myCollectionViewCell1 // 设置 Cell 视图的内容 cell.nameLabel.text = dataArray[0][indexPath.item] cell.iconImageView.image = UIImage(named: dataArray[1][indexPath.item]) return cell }
-
myCollectionViewCell.swift
class myCollectionViewCell1: UICollectionViewCell { var nameLabel:UILabel! var iconImageView:UIImageView! override init(frame: CGRect) { super.init(frame: frame) // 创建标签视图 nameLabel = UILabel(frame: CGRectMake(0, 0, self.frame.size.width, 20)) nameLabel.backgroundColor = UIColor.orangeColor() nameLabel.textAlignment = NSTextAlignment.Center self.contentView.addSubview(nameLabel) // 创建图片视图 iconImageView = UIImageView(frame: CGRectMake(0, 20, self.frame.size.width, self.frame.size.height - 20)) self.contentView.addSubview(iconImageView) } }
-
2、collectionView 的设置
-
Objective-C
// 设置表格滑动方向 /* UICollectionViewScrollDirectionVertical 垂直方向,默认 UICollectionViewScrollDirectionHorizontal 水平方向 */ flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; // 设置网格最小水平和垂直方向间距 /* 默认 10,也可以通过代理设置 */ flowLayout.minimumInteritemSpacing = 5; flowLayout.minimumLineSpacing = 30; // 设置网格背景颜色 /* 默认为黑色 */ collectionView.backgroundColor = [UIColor clearColor];
-
Swift
// 设置表格滑动方向 /* case Vertical 垂直方向,默认 case Horizontal 水平方向 */ flowLayout.scrollDirection = UICollectionViewScrollDirection.Vertical // 设置网格最小水平和垂直方向间距 /* 默认 10,也可以通过代理设置 */ flowLayout.minimumInteritemSpacing = 5 flowLayout.minimumLineSpacing = 30 // 设置网格背景颜色 /* 默认为黑色 */ collectionView.backgroundColor = UIColor.clearColor()
3、自定义 Cell 的创建与引用
-
Objective-C
-
myCollectionViewCell.h
@interface myCollectionViewCell1 : UICollectionViewCell @property(nonatomic, retain)UILabel *nameLabel; @property(nonatomic, retain)UIImageView *iconImageView; @end
-
myCollectionViewCell.m
- (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 创建标签视图 _nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, 20)]; _nameLabel.backgroundColor = [UIColor orangeColor]; _nameLabel.textAlignment = NSTextAlignmentCenter; [self.contentView addSubview:_nameLabel]; // 创建图片视图 _iconImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, self.bounds.size.width, self.bounds.size.height - 20)]; [self.contentView addSubview:_iconImageView]; } return self; }
-
ViewController.m
// 注册自定义表格视图 [collectionView registerClass:[myCollectionViewCell1 class] forCellWithReuseIdentifier:@"myCell"]; // 设置网格大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *) indexPath { return CGSizeMake((self.view.bounds.size.width - 40) / 3, 170); } // 设置每个网格的内容,cell 必须采用注册的方式自定义 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // 使用自定义 Cell 创建 myCollectionViewCell1 *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"myCell" forIndexPath:indexPath]; // 设置自定义 Cell 中视图包含的内容 cell.nameLabel.text = [myDataArray[0] objectAtIndex:indexPath.item]; cell.iconImageView.image = [UIImage imageNamed:[myDataArray[1] objectAtIndex:indexPath.item]]; return cell; }
-
-
Swift
-
myCollectionViewCell.swift
class myCollectionViewCell1: UICollectionViewCell { var nameLabel:UILabel! var iconImageView:UIImageView! override init(frame: CGRect) { super.init(frame: frame) // 创建标签视图 nameLabel = UILabel(frame: CGRectMake(0, 0, self.frame.size.width, 20)) nameLabel.backgroundColor = UIColor.orangeColor() nameLabel.textAlignment = NSTextAlignment.Center self.contentView.addSubview(nameLabel) // 创建图片视图 iconImageView = UIImageView(frame: CGRectMake(0, 20, self.frame.size.width, self.frame.size.height - 20)) self.contentView.addSubview(iconImageView) } }
-
ViewController.swift
// 注册自定义表格视图 collectionView.registerClass(myCollectionViewCell1.self, forCellWithReuseIdentifier: "myCell") // 设置网格大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize{ return CGSizeMake((self.view.bounds.size.width - 40) / 3, 170) } // 设置每个网格的内容,cell 必须用注册方式定义 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { // 使用自定义 Cell 创建 let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! myCollectionViewCell1 // 设置 Cell 视图的内容 cell.nameLabel.text = dataArray[0][indexPath.item] cell.iconImageView.image = UIImage(named: dataArray[1][indexPath.item]) return cell }
-
4、xib 自定义 Cell 的创建与引用
-
Objective-C
- myCollectionViewCell.xib

-
myCollectionViewCell.h
@interface myCollectionViewCell : UICollectionViewCell @property (weak, nonatomic) IBOutlet UILabel *nameLabel; @property (weak, nonatomic) IBOutlet UIImageView *iconImageView; @end
-
ViewController.m
// 注册自定义表格视图 [collectionView registerNib:[UINib nibWithNibName:@"myCollectionViewCell3" bundle:nil] forCellWithReuseIdentifier:@"xibCell"]; // 设置网格大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *) indexPath { return CGSizeMake(100, 170); } // 设置每个网格的内容,cell 必须采用注册的方式自定义 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // 使用自定义 Cell 创建 myCollectionViewCell3 *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"xibCell" forIndexPath:indexPath]; // 设置自定义 Cell 中视图包含的内容 cell.nameLabel.text = [dataArray[0] objectAtIndex:indexPath.item]; cell.iconImageView.image = [UIImage imageNamed:[dataArray[1] objectAtIndex:indexPath.item]]; return cell; }
-
Swift
- myCollectionViewCell.xib

-
myCollectionViewCell.swift
class myCollectionViewCell: UICollectionViewCell { @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var iconImageView: UIImageView! }
-
ViewController.swift
// 注册自定义表格视图 collectionView.registerNib(UINib(nibName: "myCollectionViewCell3", bundle: nil), forCellWithReuseIdentifier: "xibCell") // 设置网格大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize{ return CGSizeMake(100, 170) } // 设置每个网格的内容,cell 必须用注册的方式定义 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { // 使用自定义 Cell 创建 let cell = collectionView.dequeueReusableCellWithReuseIdentifier("xibCell", forIndexPath: indexPath) as! myCollectionViewCell3 // 设置 Cell 视图内容 cell.nameLabel.text = dataArray[0][indexPath.item] cell.iconImageView.image = UIImage(named: dataArray[1][indexPath.item]) return cell }
5、自定义 分段头尾的创建与引用
-
Objective-C
-
myHeaderFooterView.h
@interface myHeaderFooterView : UICollectionReusableView @property(nonatomic, retain)UILabel *nameLabel; @end
-
myHeaderFooterView.m
- (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { _nameLabel = [[UILabel alloc] initWithFrame:self.bounds]; _nameLabel.textAlignment = NSTextAlignmentCenter; _nameLabel.backgroundColor = [UIColor lightGrayColor]; [self addSubview:_nameLabel]; } return self; }
-
ViewController.m
// 注册分段头视图 [collectionView registerClass:[myHeaderFooterView1 class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"]; // 注册分段尾视图 [collectionView registerClass:[myHeaderFooterView1 class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer"]; // 设置分段头大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger) section { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30); } // 设置分段尾大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger) section { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30); } // 设置分段头尾的内容 - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *) indexPath { // collectionView 分段头尾的设置注册复用 myHeaderFooterView1 *view = nil; // 分段头 if (kind == UICollectionElementKindSectionHeader) { // 创建分段头视图 view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath]; // 设置分段头的内容 view.nameLabel.text = [NSString stringWithFormat:@"第 %ld 段 Header", indexPath.section]; } // 分段尾 else { // 创建分段尾视图 view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer" forIndexPath:indexPath]; // 设置分段尾视图的内容 view.nameLabel.text = [NSString stringWithFormat:@"第 %ld 段结束 Footer", indexPath.section]; } return view; }
-
-
Swift
-
myHeaderFooterView.swift
class myHeaderFooterView: UICollectionReusableView { var nameLabel:UILabel! override init(frame: CGRect) { super.init(frame: frame) nameLabel = UILabel(frame: self.bounds) nameLabel.textAlignment = NSTextAlignment.Center nameLabel.backgroundColor = UIColor.lightGrayColor() self.addSubview(nameLabel) } }
-
ViewController.swift
// 注册分段头视图 collectionView.registerClass(myHeaderFooterView1.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header") // 注册分段尾视图 collectionView.registerClass(myHeaderFooterView1.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "footer") // 设置分段头大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, referenceSizeForHeaderInSection:section) -> CGSize { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30) } // 设置分段尾大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, referenceSizeForFooterInSection:section) -> CGSize { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30) } // 设置分段头尾的内容 func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { var view:myHeaderFooterView1! // 分段头 if kind == UICollectionElementKindSectionHeader { // 创建分段头视图 view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "header", forIndexPath:indexPath) as! myHeaderFooterView1 // 设置分段头的内容 view.nameLabel.text = "第 \(indexPath.section) 段 Header" } // 分段尾 else { // 创建分段尾视图 view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionFooter, withReuseIdentifier: "footer", forIndexPath:indexPath) as! myHeaderFooterView1 // 设置分段尾视图的内容 view.nameLabel.text = "第 \(indexPath.section) 段 Footer" } return view }
-
6、xib 自定义 分段头尾的创建与引用
-
Objective-C
-
myHeaderFooterView.xib
-
myHeaderFooterView.h
@interface myHeaderFooterView : UICollectionReusableView @property (weak, nonatomic) IBOutlet UILabel *nameLabel; @end
-
ViewController.m
// 注册分段头视图 [collectionView registerNib:[UINib nibWithNibName:@"myHeaderFooterView2" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"xibHeader"]; // 注册分段尾视图 [collectionView registerNib:[UINib nibWithNibName:@"myHeaderFooterView2" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"xibFooter"]; // 设置分段头大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30); } // 设置分段尾大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30); } // 设置分段头尾的内容 - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { // collectionView 分段头尾的设置注册复用 myHeaderFooterView2 *view = nil; // 分段头 if (kind == UICollectionElementKindSectionHeader) { // 创建分段头视图 view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"xibHeader" forIndexPath:indexPath]; // 设置分段头的内容 view.nameLabel.text = [NSString stringWithFormat:@"第 %ld 段 xibHeader", indexPath.section]; } // 分段尾 else { // 创建分段尾视图 view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"xibFooter" forIndexPath:indexPath]; // 设置分段尾视图的内容 view.nameLabel.text = [NSString stringWithFormat:@"第 %ld 段结束 xibFooter", indexPath.section]; } return view; }
-
-
Swift
-
myHeaderFooterView.xib
-
myHeaderFooterView.swift
class myHeaderFooterView: UICollectionReusableView { @IBOutlet weak var nameLabel: UILabel! }
-
ViewController.swift
// 注册分段头视图 collectionView.registerNib(UINib(nibName: "myHeaderFooterView2", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "xibHeader") // 注册分段尾视图 collectionView.registerNib(UINib(nibName: "myHeaderFooterView2", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "xibFooter") // 设置分段头大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, referenceSizeForHeaderInSection:section) -> CGSize { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30) } // 设置分段尾大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, referenceSizeForFooterInSection:section) -> CGSize { /* width 为水平滑动时,间距有效。height 为垂直滑动时,间距有效。 */ return CGSizeMake(20, 30) } // 设置分段头尾的内容 func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { var view:myHeaderFooterView2! // 分段头 if kind == UICollectionElementKindSectionHeader { // 创建分段头视图 view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "xibHeader", forIndexPath:indexPath) as! myHeaderFooterView2 // 设置分段头的内容 view.nameLabel.text = "第 \(indexPath.section) 段 Header" } // 分段尾 else { // 创建分段尾视图 view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionFooter, withReuseIdentifier: "xibFooter", forIndexPath:indexPath) as! myHeaderFooterView2 // 设置分段尾视图的内容 view.nameLabel.text = "第 \(indexPath.section) 段 Footer" } return view }
-
7、自定义布局风格
-
Objective-C
-
CustomLayout.h
@interface CustomLayout : UICollectionViewLayout
-
CustomLayout.m
/* 简单定义了一个 section 的布局 */ @implementation CustomLayout // 设置网格视图的大小 - (CGSize)collectionViewContentSize { // 每行显示 3 个图标,1大2小 return CGSizeMake(self.collectionView.bounds.size.width, [self.collectionView numberOfItemsInSection:0 / 3] * 200 + 200); } // 设置单元格的位置属性 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { NSMutableArray *attributesArray = [[NSMutableArray alloc] init]; NSUInteger cellCount = [self.collectionView numberOfItemsInSection:0]; for (int i = 0; i < cellCount; i++) { UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; [attributesArray addObject:attributes]; } return attributesArray; } // 设置单元格的位置与大小 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { // 获取当前单元格布局属性 UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; // 单元格边长 CGFloat largeCellSide = 200; CGFloat smallCellSide = 100; // 单元格间距 // NSUInteger itemSpacing = 2; NSUInteger lineSpacing = 5; // 边距 UIEdgeInsets insets = UIEdgeInsetsMake(2, 20, 2, 20); // 当前行数 /* 每行显示 3 个图片,1 大 2 小 */ NSInteger line = indexPath.item / 3; // 当前行的 Y 坐标 CGFloat lineOriginY = insets.top + largeCellSide * line + lineSpacing * line; // 右侧单元格 X 坐标 /* 这里按左右对齐,所以中间空隙大 */ CGFloat rightLargeX = self.collectionView.bounds.size.width - largeCellSide - insets.right; CGFloat rightSmallX = self.collectionView.bounds.size.width - smallCellSide - insets.right; // 每行 2 个图片,2 行循环一次,一共 6 种位置 if (indexPath.item % 6 == 0) { attribute.frame = CGRectMake(insets.left, lineOriginY, largeCellSide, largeCellSide); } else if (indexPath.item % 6 == 1) { attribute.frame = CGRectMake(rightSmallX, lineOriginY, smallCellSide, smallCellSide); } else if (indexPath.item % 6 == 2) { attribute.frame = CGRectMake(rightSmallX, lineOriginY + smallCellSide + insets.top, smallCellSide, smallCellSide); } else if (indexPath.item % 6 == 3) { attribute.frame = CGRectMake(insets.left, lineOriginY, smallCellSide, smallCellSide); } else if (indexPath.item % 6 == 4) { attribute.frame = CGRectMake(insets.left, lineOriginY + smallCellSide + insets.top, smallCellSide, smallCellSide); } else if (indexPath.item % 6 == 5) { attribute.frame = CGRectMake(rightLargeX, lineOriginY, largeCellSide, largeCellSide); } return attribute; }
-
ViewController.m
// 数据源初始化 // 声明数据源 @property(nonatomic, retain)NSMutableArray *dataArray; dataArray = [NSMutableArray arrayWithObjects: @{@"name":@"Swift" , @"pic":@"swift.png" }, @{@"name":@"OC" , @"pic":@"oc.jpg" }, @{@"name":@"Java" , @"pic":@"java.png" }, @{@"name":@"PHP" , @"pic":@"php.jpeg" }, @{@"name":@"JS" , @"pic":@"js.jpeg" }, @{@"name":@"HTML" , @"pic":@"html.jpeg" }, @{@"name":@"Ruby" , @"pic":@"ruby.png" }, nil]; // 网格视图初始化 // 声明网格视图 @property(nonatomic, retain)UICollectionView *myCollectionView; CustomLayout *layout = [[CustomLayout alloc] init]; myCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height - 20) collectionViewLayout:layout]; // 默认背景是黑色和 label 一致 myCollectionView.backgroundColor = [UIColor whiteColor]; myCollectionView.delegate = self; myCollectionView.dataSource = self; // 注册 CollectionViewCell [myCollectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"myCell"]; [self.view addSubview:myCollectionView]; // UICollectionView 协议方法 // 设置行数 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return dataArray.count; } // 设置网格显示的内容 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // 创建 cell UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"myCell" forIndexPath:indexPath]; // 创建自定义 cell 视图 UIImageView *imageView = [[UIImageView alloc] initWithFrame:cell.bounds]; imageView.image = [UIImage imageNamed:dataArray[indexPath.item][@"pic"]]; [cell addSubview:imageView]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 5, cell.bounds.size.width, 20)]; label.text = dataArray[indexPath.item][@"name"]; label.textAlignment = NSTextAlignmentCenter; [cell addSubview:label]; return cell; }
-
-
Swift
-
CustomLayout.swift
/* 简单定义了一个 section 的布局 */ class CustomLayout: UICollectionViewLayout // 设置网格视图的大小 override func collectionViewContentSize() -> CGSize { // 每行显示 3 个图标,1大2小 return CGSizeMake(collectionView!.bounds.size.width, CGFloat((collectionView!.numberOfItemsInSection(0) / 3) * 200 + 200)) } // 设置单元格的位置属性 override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var attributesArray = Array<UICollectionViewLayoutAttributes>() let cellCount = self.collectionView!.numberOfItemsInSection(0) for i in 0..<cellCount { let attributes = self.layoutAttributesForItemAtIndexPath(NSIndexPath(forItem: i, inSection: 0)) attributesArray.append(attributes!) } return attributesArray } // 设置单元格的位置与大小 override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { // 获取当前单元格布局属性 let attribute = UICollectionViewLayoutAttributes(forCellWithIndexPath:indexPath) // 单元格边长 let largeCellSide = CGFloat(200) let smallCellSide = CGFloat(100) // 单元格间距 let itemSpacing = 2 let lineSpacing = 5 // 边距 let insets = UIEdgeInsetsMake(2, 20, 2, 20) // 当前行数 /* 每行显示 3 个图片,1 大 2 小 */ let line = indexPath.item / 3 // 当前行的 Y 坐标 let lineOriginY = insets.top + largeCellSide * CGFloat(line) + CGFloat(lineSpacing * line) // 右侧单元格 X 坐标 /* 这里按左右对齐,所以中间空隙大 */ let rightLargeX = collectionView!.bounds.size.width - largeCellSide - insets.right let rightSmallX = collectionView!.bounds.size.width - smallCellSide - insets.right // 每行 2 个图片,2 行循环一次,一共 6 种位置 if (indexPath.item % 6 == 0) { attribute.frame = CGRectMake(insets.left, lineOriginY, largeCellSide, largeCellSide) } else if (indexPath.item % 6 == 1) { attribute.frame = CGRectMake(rightSmallX, lineOriginY, smallCellSide, smallCellSide) } else if (indexPath.item % 6 == 2) { attribute.frame = CGRectMake(rightSmallX, lineOriginY + smallCellSide + insets.top, smallCellSide, smallCellSide) } else if (indexPath.item % 6 == 3) { attribute.frame = CGRectMake(insets.left, lineOriginY, smallCellSide, smallCellSide) } else if (indexPath.item % 6 == 4) { attribute.frame = CGRectMake(insets.left, lineOriginY + smallCellSide + insets.top, smallCellSide, smallCellSide) } else if (indexPath.item % 6 == 5) { attribute.frame = CGRectMake(rightLargeX, lineOriginY, largeCellSide, largeCellSide) } return attribute }
-
ViewController.swift
// 数据源初始化 // 声明数据源 var dataArray:[[String:String]] = Array() dataArray = [ ["name":"Swift" , "pic":"swift.png" ], ["name":"OC" , "pic":"oc.jpg" ], ["name":"Java" , "pic":"java.png" ], ["name":"PHP" , "pic":"php.jpeg" ], ["name":"JS" , "pic":"js.jpeg" ], ["name":"HTML" , "pic":"html.jpeg" ], ["name":"Ruby" , "pic":"ruby.png" ] ] // 网格视图初始化 var myCollectionView:UICollectionView! // 声明网格视图 let layout = CustomLayout() myCollectionView = UICollectionView(frame: CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height - 20), collectionViewLayout:layout) // 默认背景是黑色和 label 一致 myCollectionView.backgroundColor = UIColor.whiteColor() myCollectionView.delegate = self myCollectionView.dataSource = self // 注册 CollectionViewCell myCollectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "myCell") self.view.addSubview(myCollectionView) // UICollectionView 协议方法 // 设置行数 func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return dataArray.count } // 设置网格显示的内容 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { // 创建 cell let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) // 创建自定义 cell 视图 let imageView = UIImageView(frame: cell.bounds) imageView.image = UIImage(named: dataArray[indexPath.item]["pic"]!) cell.addSubview(imageView) let label = UILabel(frame:CGRectMake(0, 5, cell.bounds.size.width, 20)) label.text = dataArray[indexPath.item]["name"] label.textAlignment = NSTextAlignment.Center cell.addSubview(label) return cell }
-
8、UICollectionView 协议方法
需遵守协议 UICollectionViewDataSource, UICollectionViewDelegate,并设置代理
-
Objective-C
-
分段、网格 设置
// 设置分段数 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 3; } // 设置网格数 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return 15; } // 设置网格大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(100, 170); } // 设置每个网格的内容 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { /* cell 必须采用注册的方式自定义 */ return cell; }
-
网格间距设置
// 设置最小网格间距 - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { /* 垂直滑动时,系统会根据屏幕宽度和网格(cell)的宽度在大于等于最小网格(cell)间距的范围内自动调整。 水平滑动时,系统会根据屏幕高度和网格(cell)的高度在大于等于最小网格(cell)间距的范围内自动调整。 */ return 10; } // 设置最小行间距 - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 10; } // 设置分段周边距 - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { // 上,左,下,右 return UIEdgeInsetsMake(20, 10, 20, 10); }
-
分段头尾 设置
// 设置分段头大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { /* width 为水平滑动时的间距有效,height 为垂直滑动时的间距有效 */ return CGSizeMake(20, 30); } // 设置分段尾大小 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { /* width 为水平滑动时的间距有效,height 为垂直滑动时的间距有效 */ return CGSizeMake(20, 30); } // 设置分段头尾视图 - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { return myView; }
-
网格点击 设置
// 网格点击 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { } // 网格取消点击,点击另一个表格的时候触发 - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath { }
-
-
Swift
-
分段、网格 设置
// 设置分段数 func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { return 3 } // 设置网格数 func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 15 } // 设置网格大小 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize { return CGSizeMake(100, 170) } // 设置每个网格的内容 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { /* cell 必须采用注册的方式自定义 */ return cell }
-
网格间距 设置
// 设置最小网格间距 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, minimumInteritemSpacingForSectionAtIndex:section) -> CGFloat { /* 垂直滑动时,系统会根据屏幕宽度和网格(cell)的宽度在大于等于最小网格(cell)间距的范围内自动调整。 水平滑动时,系统会根据屏幕高度和网格(cell)的高度在大于等于最小网格(cell)间距的范围内自动调整。 */ return 10 } // 设置最小行间距 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, minimumLineSpacingForSectionAtIndex:section) -> CGFloat { return 50 } // 设置分段周边距 func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, insetForSectionAtIndex:section) -> UIEdgeInsets { // 上,左,下,右 return UIEdgeInsetsMake(20, 20, 20, 20) }
-
分段头尾 设置
// 设置分段头大小 func collectionView(collectionView: UICollectionView!, layut collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection:section) -> CGSize { /* width 为水平滑动时的间距有效,height 为垂直滑动时的间距有效 */ return CGSizeMake(20, 30) } // 设置分段尾大小 func collectionView(collectionView: UICollectionView!, layut collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection:section) -> CGSize { /* width 为水平滑动时的间距有效,height 为垂直滑动时的间距有效 */ return CGSizeMake(20, 30) } // 设置分段头尾视图 func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { return myView }
-
网格点击 设置
// 网格点击 func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { } // 网格取消点击,点击另一个表格的时候触发 func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) { }
-
9、Storyboard 中设置
-
在 Storyboard 场景中设置
-
Collection View Controller
Selection ... Clear on Appearance -
Collection View
Items 设置不同类型的单元格数量 Layout 设置布局类型 Scroll Direction 设置网格滑动方向 Accessories Section Header 显示网格头 Section Footer 显示网格尾 Cell Size 网格单元的大小 Header Size 网格头的大小 Footer Size 网格尾的大小 Min Spacing 最小行列间距 Section Insets 网格边距 -
Collection Reusable View
-
-
在 Storyboard 场景绑定的 Controller 中设置
- 在 Storyboard 自带的 collectionViewCell 中没有 contentView,在使用 Cell 时显示的内容必须使用代码自定义,其它设置可以在系统自带的 Cell 上设置。