CollectionView的详细使用(一)
tableView与collectionView比较
- 相同点
- 都是通过
datasource
和delegate
驱动的,因此在使用的时候必须实现数据源与代理协议方法; - 性能上都实现了循环利用的优化。
- 都继承自
UIScrollView
- 都是通过
- 不同点
UITableView
的cell
是系统自动布局好的,不需要我们布局(垂直分布,一行一行排列)。但是UICollectionView
的cell
是需要自己布局的(每个item
如何排布)。-
因此在创建
UICollectionView
的时候必须传递一个布局参数,而且这个参数必须是UICollectionViewLayout
的子类- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
-
系统默认提供并实现了一个布局样式:流水布局(
UICollectionViewFlowLayout
)
-
UITableViewController
的self.view == self.tableview;
,但UICollectionViewController
的self.view != self.collectionView
UICollectionViewController
层次结构:控制器View
上面UICollectionView
UITableView
的滚动方式只能是垂直方向,UICollectionView
既可以垂直滚动,也可以水平滚动;UICollectionView
的cell
只能通过注册来确定重用标识符。不能像tableViewcell
一样initWith...
- 并不能直接设置
cell
的高度/section
之间距离的数据源方法,只能通过设置layout
来实现
- 结论 : 换句话说,UITableView的布局是UICollectionView的flow layout布局的一种特殊情况,类比于同矩形与正方形的关系
-
代码举例:
CGRect frame = CGRectZero; UICollectionView *collection = [[UICollectionView alloc] init]; collection.frame = frame; [self.view addSubview:collection]; //运行报错: //reason: UICollectionView must be initialized with a non-nil layout parameter //意思:collctionView初始化时必须要传一个非空布局(layout)参数(parameter); // 因此初始化方法如下: UICollectionView *collection = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:[[UICollectionViewFlowLayout alloc] init]];
UICollectionViewFlowLayout
- 系统自定义布局,流水布局,即:像流水一样一行满了,排下一行
UICollectionViewLayout
的子类CollectionViewcell
排布的样式是由UICollectionViewLayout
决定的- 该类常用属性如下:
-
最小行间距与最小垂直间距
//设置最小行间距 minimumLineSpacing // 设置垂直间距 minimumInteritemSpacing
- 注意:为何是最小(minimum)呢? 怎么不直接是行间距与列间距呢?
- 分析:
- 情况1:
- 同一行有不同的size的cell.由于高度不同,那么最小行间距就是本行最高的cell距离下一行最高cell的间距
-
同理,同一列有不同size的cell,由于宽度不同,那么最大列间距就是本列最宽cell距离下一列最宽cell的间距
- 情况2:
-
cell
的itemsize
已经设置固定,行间距再固定,那么界面排版就冲突,因此设置最小间距
-
- 情况1:
-
其他属性
//每个cell统一尺寸,系统默认50*50 itemSize //预估cell的尺寸,ios8之后可以先去预估cell的尺寸,然后去自适应(与tableView相似) estimatedItemSize //一行代码足以,不需要向tableView2行代码 layout.estimatedItemSize = CGSizeMake( 60, 60); //设置滚动方向(默认垂直滚动) scrollDirection //每一组头视图的尺寸。如果是垂直方向滑动,则只有高起作用;如果是水平方向滑动,则只有宽起作用。 headerReferenceSize //每一组尾部视图的尺寸。如果是垂直方向滑动,则只有高起作用;如果是水平方向滑动,则只有宽起作用。 footerReferenceSize //每一组的内容缩进,每个section的内部缩进 sectionInset //每一个section的header都是悬浮(iOS9) sectionHeadersPinToVisibleBounds //每一个section的footer都是悬浮(iOS9) sectionFootersPinToVisibleBounds
-
代码举例:制作一个简单启动广告页
AppDelegate中代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIWindow *window = [[UIWindow alloc] init];
window.frame = [UIScreen mainScreen].bounds;
window.rootViewController =[[CollectionViewController alloc] init];
self.window = window;
[window makeKeyAndVisible];
return YES;
}
//自定义的CollectionViewController控制器:
//CollectionViewController.m文件
// UICollection的基本使用-启动页制作
#import "ViewController.h"
#import "CollectionViewController.h"
@interface CollectionViewController ()
@end
@implementation CollectionViewController
static NSString * const reuseIdentifier = @"Cell";
- (void)viewDidLoad {
[super viewDidLoad];
//可以看到self.view != self.collectionView
self.view.backgroundColor = [UIColor redColor];
self.collectionView.backgroundColor = [UIColor greenColor];
//取消弹簧效果
self.collectionView.bounces = NO;
//水平方向的滚动条
self.collectionView.showsHorizontalScrollIndicator = NO;
//分页滚动
self.collectionView.pagingEnabled = YES;
//1.必须通过注册cell
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
}
//2.重写init方法,传值layout
// 初始化的时候必须设置布局参数,通常使用系统提供的流水布局UICollectionViewFlowLayout
-(instancetype)init{
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
// 设置滚动的方向
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 设置cell的尺寸
layout.itemSize = [UIScreen mainScreen].bounds.size;
// 设置cell之间间距
layout.minimumInteritemSpacing = 0;
// 设置行距
layout.minimumLineSpacing = 0;
// 设置每一组的内间距
// layout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);
return [super initWithCollectionViewLayout:layout];
}
//3.实现代理数据源方法
#pragma mark <UICollectionViewDataSource>
//返回多少组
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
//每组多少个cell
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 4;;
}
//返回展示的cell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
//自定义cell,在cell里面放一张图片即可(略)
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (![cell.contentView viewWithTag:-100]) {
UISwitch *sw = UISwitch.new;
sw.tag = -100;
[cell.contentView addSubview:[UISwitch new]];
}
cell.backgroundColor = [UIColor blueColor];
return cell;
}
#pragma mark <UICollectionViewDelegate>
//点击最后一张时替换掉keyWindow的rootViewcontroller
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.item == 3) {
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
UIViewController *VC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateInitialViewController];
keyWindow.rootViewController = VC;
}
}
//在这里检测到,一旦替换掉,当前控制器就会被销毁
-(void)dealloc{
NSLog(@"对象已经销毁");
}
@end
效果图如下