说句老实话,UICollectionView真的太强大了,而且要掌握高级部分是相当困难的。至少笔者是这么认为的,如果觉得自己比较厉害,可以轻而易举地掌握UICollectionView的使用的,希望可以总结点经验!
本篇文章是在练习如何使用UICollectionView进行网格布局。网格布局是非常常见的UI布局,在很多的App中都这么设计过。本篇文章只讲如何实现风格布局,demo中有一些是优化方面的,会单独写一篇文章讲解如何优化网格布局中的图片。
实现效果
FlowLayout
本demo中需要使用到UICollectionViewFlowLayout,因此先讲讲这个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// iOS6.0以后才有的 NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewFlowLayout : UICollectionViewLayout // 行之间的最小间距 @property (nonatomic) CGFloat minimumLineSpacing; // item之间的最小间距 @property (nonatomic) CGFloat minimumInteritemSpacing; // 如果cell的大小是固定的,应该直接设置此属性,就不用实现代理 @property (nonatomic) CGSize itemSize; // 这是8.0后才能使用,评估item的大小 @property (nonatomic) CGSize estimatedItemSize NS_AVAILABLE_IOS(8_0); // 支持两种滚动方向,水平滚动和竖直功能 // 因此不要再想要使用横向tableview,直接使用collectionview就okb @property (nonatomic) UICollectionViewScrollDirection scrollDirection; // header参考大小 @property (nonatomic) CGSize headerReferenceSize; // footer参考大小 @property (nonatomic) CGSize footerReferenceSize; // section的inset,用于设置与上、左、底、右的间隔 @property (nonatomic) UIEdgeInsets sectionInset; // 9.0以后才有的属性,用于设置header/footer与tableview的section效果一样。 // 可以悬停 @property (nonatomic) BOOL sectionHeadersPinToVisibleBounds NS_AVAILABLE_IOS(9_0); @property (nonatomic) BOOL sectionFootersPinToVisibleBounds NS_AVAILABLE_IOS(9_0); @end |
这个类是用于决定UICollectionView的item的布局的。
创建CollectionView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// 创建UI布局 UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; // 设置成固定的大小 layout.itemSize = CGSizeMake((kScreenWidth - 30) / 2, (kScreenWidth - 30) / 2 + 20); // 行间距最小设置为10 layout.minimumLineSpacing = 10; // 列间距最小设置为10 layout.minimumInteritemSpacing = 10; self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; [self.view addSubview:self.collectionView]; // 注册cell [self.collectionView registerClass:[HYBGridCell class] forCellWithReuseIdentifier:cellIdentifier]; // 设置代理 self.collectionView.delegate = self; self.collectionView.backgroundColor = [UIColor blackColor]; // 设置数据源代理 self.collectionView.dataSource = self; |
实现代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#pragma mark - UICollectionViewDataSource & UICollectionViewDelegate - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { HYBGridCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; HYBGridModel *model = self.datasource[indexPath.item]; [cell configCellWithModel:model]; return cell; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.datasource.count; } |
创建一个对应的cell,这里呢实现只是简单的添加两个控件而已:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.imageView = [[UIView alloc] init]; self.imageView.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.width); [self.contentView addSubview:self.imageView]; self.titleLabel = [[UILabel alloc] init]; self.titleLabel.frame = CGRectMake(0, self.frame.size.height - 20, self.frame.size.width, 20); self.titleLabel.numberOfLines = 0; self.titleLabel.font = [UIFont systemFontOfSize:16]; self.titleLabel.textColor = [UIColor whiteColor]; self.titleLabel.backgroundColor = [UIColor blackColor]; self.titleLabel.layer.masksToBounds = YES; [self.contentView addSubview:self.titleLabel]; } return self; } |