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, 遵守協議實現方法