UICollectionView网格视图
网格视图是能够显示多列的列表视图, 弥补了UITableView不方便实现多列的缺点, 在iOS6之后才有这个控件
Inheritance
NSObject
UIResponder
UIView
UIScrollView
UICollectionView
UICollectionViewFlowLayout: 确定网格视图的布局
上下左右的间距: sectionInset(left, top, bottom, right)
每一个Cell的大小: itemSize(width, height)
横向Cell之间的间距: minimumInteritemSpacing
纵向Cell之间的间距: minimumLineSpacing
目录
一.单分组的网格视图
- 系统的Cell
- 代码自定制的Cell
- xib自定义Cell
二.多分组的网格视图
- Header
- Footer
三.实现穷游App的折扣界面
- 创建模型类, 导入MyDownloader类(用于从网上下载数据)
- 解析下载到的JSON数据, 创建数据源(此处下载到的是JSON数据, 以后也可能需要下载解析XML数据)
- 自定义Cell
- 常规流程: 创建CollectionView, 遵守协议实现方法
一.单分组的网格视图
-
使用系统的Cell
创建数据源
-
创建UICollectionView对象
-
指定初始化方法
// 第一个参数: 位置 // 第二个参数: 布局对象 - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 20, kWidthOfScreen, kHeightOfScreen - 20) collectionViewLayout:layout];
-
布局对象 UICollectionViewLayout
// 布局对象是一个UICollectionViewLayout类型的对象 // 由于我们是规则的布局, 可以直接使用UICollectionViewFlowLayout对象 // UICollectionViewFlowLayout继承于UICollectionViewLayout UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; // 1. 上下左右的间距 /* UIEdgeInsets:<#CGFloat top#>(上面的间距), <#CGFloat left#>(左边), <#CGFloat bottom#>(底部), <#CGFloat right#>(右边) */ layout.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5); // 2. cell的大小 layout.itemSize = CGSizeMake(180, 100); // 3. 横向间距 layout.minimumInteritemSpacing = 5; // 4. 纵向间距 layout.minimumLineSpacing = 10;
-
设置UICollectionView对象的属性
// 设置代理 collectionView.delegate = self; // 设置数据源代理 collectionView.dataSource = self; // 设置白色背景 collectionView.backgroundColor = [UIColor whiteColor]; // 注册cell的类型 // 以代码的方式注册Cell的类型, 表示创建Cell的时候用这个类型来创建 /* 第一个参数: Cell的类型 第二个参数: 重用标志 */ [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kCellReuseId]; // 添加到父视图上 [self.view addSubview:collectionView];
-
-
遵守协议, 实现协议方法
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
// 返回每一个Cell的对象 // UICollectionView上面的每一个Cell是UICollectionViewCell类型(或子类型)的对象 // UICollectionViewCell也是一个视图 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // 从重用队列里面获取 /* 第一个参数: 重用id 第二个参数: cell的位置 */ // UITableView -> NSIndexPath:section row // UICollectionView -> NSIndexPath:section item UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellReuseId forIndexPath:indexPath]; // 不需要再创建, 从dequeueReusableCellWithReuseIdentifier方法李米娜一定能够获取到 // 设置背景颜色 cell.backgroundColor = [UIColor grayColor]; // 显示文字 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 30, 180, 40)]; label.textAlignment = NSTextAlignmentCenter; // 获取文字 NSString *str = self.dataArray[indexPath.item]; label.text = str; // 添加到父视图 [cell.contentView addSubview:label]; return cell; }
-
因为每次都是新添一个UILabel, 所以会有滑动出现重影的问题(其实是UILabel的重叠)
// 解决方法, 在为cell设新的UILabel前移除之前的子视图 for (UIView *sub in cell.contentView.subviews) { [sub removeFromSuperview]; }
-
代码自定制的Cell
- 创建数据源
- 创建UICollectionView对象
- 指定初始化方法
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout; - 布局对象 UICollectionViewLayout
- 设置UICollectionView对象的属性
- 指定初始化方法
- 遵守协议, 实现协议方法
- 因为自建的cell的控件是其属性, 所以每次重新设置cell的控件的属性不会发生重影的问题
-
Xib定制的Cell
创建数据源
-
创建UICollectionView对象
指定初始化方法
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;-
布局对象 UICollectionViewLayout (可以使用UICollectionViewDelegateFlowLayout代理来设置)
Getting the Size of Items – collectionView:layout:sizeForItemAtIndexPath: Getting the Section Spacing – collectionView:layout:insetForSectionAtIndex: – collectionView:layout:minimumLineSpacingForSectionAtIndex: – collectionView:layout:minimumInteritemSpacingForSectionAtIndex: Getting the Header and Footer Sizes – collectionView:layout:referenceSizeForHeaderInSection: – collectionView:layout:referenceSizeForFooterInSection:
设置UICollectionView对象的属性
-
注册cell的类型
// 注册cell(xib) // 第一个参数: xib的对象(UINib类型) // 第二个参数: 重用标志 UINib *nib = [UINib nibWithNibName:@"DataCell" bundle:nil]; [collectionView registerNib:nib forCellWithReuseIdentifier:kCellReuseId];
遵守协议, 实现协议方法
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 从重用列表中获取
DataCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellReuseId forIndexPath:indexPath];
..........................................................................
}
代码自定制的cell和xib的区别:注册Cell方法的不同
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
二.多分组的网格视图
-
Header
新建headerView类, 继承自UICollectionReusableView
-
注册header
/* 第一个参数:header视图对象的类型 第二个参数:区分是header还是后面的footer // UICollectionElementKindSectionHeader表示header类型 第三个参数:重用标志 */ [_collectionView registerClass:[HeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:KHeaderReuseId];
在布局对象的代理协议方法中设置header的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(375, 40);
}-
返回header对象 UICollectionViewDataSource的协议方法(也可以用来返回footer对象)
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
if (kind == UICollectionElementKindSectionHeader) {
// header类型// 从重用队列里面获取 HeaderView *header = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:KHeaderReuseId forIndexPath:indexPath]; // 设置背景颜色 header.backgroundColor = [UIColor redColor]; // 显示数据 header.titleLabel.text = [NSString stringWithFormat:@"第%c组", (int)(indexPath.section + 'A')]; return header; } else if (kind == UICollectionElementKindSectionFooter) { // footer // 从重用队列里面获取 FooterView *footer = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:KFooterReuseId forIndexPath:indexPath]; footer.backgroundColor = [UIColor purpleColor]; // 显示数据 footer.titleLabel.text = [NSString stringWithFormat:@"第%c组结束", (int)(indexPath.section + 'A')]; return footer; } return nil; }
-
Footer
新建FooterView类, 继承自UICollectionReusableView
-
注册footer
[_collectionView registerClass:[FooterView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:KFooterReuseId];
在布局对象的代理协议方法中设置footer的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
return CGSizeMake(375, 40);
}返回footer对象 UICollectionViewDataSource的协议方法(也可以用来返回header对象)
三.实现穷游App的折扣界面
-
创建模型类, 导入MyDownloader类(用于从网上下载数据)
// 下载数据 - (void)downloadData { // 创建myDownloader对象 MyDownloader *downloader = [[MyDownloader alloc] init]; // 设置代理 downloader.delegate = self; // 下载数据 [downloader downloadWithUrlString:kUrl]; } // MyDownloader代理方法 // 下载失败 - (void)downloaderFail:(NSError *)error downloader:(MyDownloader *)downloader { NSLog(@"%@", error); }
-
解析下载到的JSON数据, 创建数据源(此处下载到的是JSON数据, 以后也可能下载XML数据)
// 下载成功 - (void)downloaderFinish:(MyDownloader *)downloader { // 下载回来的数据在downloader.receiveData这个属性里 // JSON解析 id result = [NSJSONSerialization JSONObjectWithData:downloader.receiveData options:NSJSONReadingMutableContainers error:nil]; if ([result isKindOfClass:[NSDictionary class]]) { // 如果是字典 按照字典来操作 NSDictionary *dict = result; NSArray *array = dict[@"data"]; for (NSDictionary *dataDict in array) { // NSLog(@"%@", dataDict); // 创建模型对象 DataModel *model = [[DataModel alloc] init]; [model setValuesForKeysWithDictionary:dataDict]; // 添加到数组中 [self.dataArray addObject:model]; } // 刷新网格视图 [_collectionView reloadData]; } }
- 因为上方使用KVC方法来创建模型对象, 所以我们要在模型类的.m文件中重写方法
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
}
- 因为上方使用KVC方法来创建模型对象, 所以我们要在模型类的.m文件中重写方法
-
自定义Cell
-
DataCell.m
- (void)config:(DataModel *)model
{
// 图片
[self.picImageView sd_setImageWithURL:[NSURL URLWithString:model.pic]];// 价格 self.priceLabel.text = model.buy_price; // 名字 self.nameLabel.text = model.title; self.nameLabel.numberOfLines = 2; self.nameLabel.font = [UIFont boldSystemFontOfSize:18]; // 时间 self.timeLabel.text = model.end_date; // 折扣 self.discountLabel.text = model.lastminute_des; }
- 因为我们的图片是从根据一个网址的字符串去网上下载的,所以我们导入了另一个第三方库UIImageView+WebCache 用于下载网上图片
- (void)sd_setImageWithURL:(NSURL *)url
{
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}
- 因为我们的图片是从根据一个网址的字符串去网上下载的,所以我们导入了另一个第三方库UIImageView+WebCache 用于下载网上图片
-
-
常规流程: 创建CollectionView, 遵守协议实现方法