UICollectionViewController的使用详解
// 设置 collectionView 的数据源代理
_collectionView.dataSource = self;
// 修改collectionView的背景色
_collectionView.backgroundColor = [UIColor whiteColor];
// 隐藏滚动条
_collectionView.showsHorizontalScrollIndicator = NO;
// 设置分页效果
_collectionView.pagingEnabled = YES;
// 设置弹簧效果
_collectionView.bounces = NO;
/**
collectionView 必须有一个 layout
在storyboard 上拖拽的时候, 已经自动添加一个 流水布局
UICollectionView must be initialized with a non-nil layout parameter
*/
/**
实例化一个layout对象
collectionView 如果要使用layout 必须在实例化的时候就进行设置
UICollectionViewLayout 是流水布局的父类, 最纯净的layout
UICollectionViewFlowLayout 是在父类上做了一些相应的扩展
*/
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
// 修改cell 的大小 , 默认是 50 , 50
flowLayout.itemSize = CGSizeMake(100, 100);
// 修改cell距离view的边距
_flowLayout.sectionInset = UIEdgeInsetsMake(40, 10, 0, 10);
// 修改滚动方向
// _flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 下面两个属性是和 滚动方向有关的
// 最小列之间的间距
_flowLayout.minimumInteritemSpacing = 50;
// 设置最小行间距
// flowLayout.minimumLineSpacing = 100;
// 实例化一个collectionView
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];
collectionView.dataSource = self;
// 添加到控制器的view上
[self.view addSubview:collectionView];
// 设置背景色
collectionView.backgroundColor = [UIColor whiteColor];
// 注册一个cell
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:identifier];
/**
取出 collectionView的 flowlayout
self.collectionViewLayout 只读的
self.collectionView.collectionViewLayout 做一步强转
*/
UICollectionViewFlowLayout *folowLayout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
folowLayout.itemSize = CGSizeMake(100, 100);
// Pin 钉住, 类似tableView的悬浮效果
folowLayout.sectionFootersPinToVisibleBounds = YES;
folowLayout.sectionHeadersPinToVisibleBounds = YES;
// 在垂直滚动的时候, 设置宽度无效
// 水平滚动的时候, 设置高度无效
// folowLayout.headerReferenceSize = CGSizeMake(10, 50);//设置头部宽度
// folowLayout.footerReferenceSize = CGSizeMake(20, 70);
// 取消选中
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"取消选中 - %ld", indexPath.item);
}
// 被选中
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// item 就相当于row
NSLog(@"%ld", indexPath.item);
}
#pragma mark - 这个方法会反回所有cell的属性设置
// 反回的数组中, 是 UICollectionViewLayoutAttributes 对象, 包含了cell的属性
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
// 1. 取出所有的item 的 UICollectionViewLayoutAttributes
NSArray *superAttributes = [super layoutAttributesForElementsInRect:rect];
// 2. 计算出屏幕的中心点, 中心点必须加上 collectionView的偏移量.x
CGFloat screenCenter = self.collectionView.contentOffset.x + self.collectionView.frame.size.width/2;
// 通过循环遍历 可以对 item的属性进行修改
for (UICollectionViewLayoutAttributes *itemAttributes in superAttributes) {
// 3. 计算差值 ABS() 取绝对值
CGFloat deltaMargin = ABS(screenCenter - itemAttributes.center.x);
// 4. 计算一个放大比率 , cell 和中心点的距离 和 方大的比率成反比
CGFloat scaleDelta = 1.1 - deltaMargin / (self.collectionView.frame.size.width/2 + itemAttributes.size.width);
itemAttributes.transform = CGAffineTransformMakeScale(scaleDelta, scaleDelta);
}
return superAttributes;
}
#pragma mark -
#pragma mark - 当手指离开collectionView的时候会调用
/**
targetContentOffset --- > 最终停留的位置 (进行干预后停留的位置)
ProposedContentOffset ---> 本应该停留的位置
velocity 力度, 速度
*/
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
// 1. 取出屏幕的中心点
CGFloat screenCenter = proposedContentOffset.x + self.collectionView.frame.size.width/2;
// 2. 取出可见范围内的cell
CGRect visibleRect = CGRectZero;
visibleRect.size = self.collectionView.frame.size;
visibleRect.origin = proposedContentOffset;
// 得到的是 可见范围内的cell属性集合 调用super 的方法, 是避免重新计算比率
NSArray *visibleArray = [super layoutAttributesForElementsInRect:visibleRect];
//定义最小的间距
CGFloat minMargin=MAXFLOAT;
for(UICollectionViewLayoutAttributes *attributes in visibleArray){
//取出cell的中心和屏幕中心的间距
CGFloat delMargin=attributes.center.x-screenCenter;
if (ABS(minMargin)>ABS(delMargin)) {
minMargin=delMargin;
}
}
return CGPointMake(proposedContentOffset.x+minMargin, proposedContentOffset.y);
}
#pragma mark -
#pragma mark - 当屏幕的可见范围发生变化的时候, 要重新刷新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}
#pragma mark -
#pragma mark - 当布局刷新的时候, 就会自动调用这个方法
// 建议在这个方法里进行初始化的设置
- (void)prepareLayout {
[super prepareLayout];
// 修改滚动方向
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 取出collectionView的size
CGSize collectionViewSize = self.collectionView.frame.size;
// 设置item的宽高
CGFloat itemWidth = collectionViewSize.height * 0.6;
// 设置item的高度
CGFloat itemHeight = collectionViewSize.height * 0.8;
// 修改item的size
self.itemSize = CGSizeMake(itemWidth, itemHeight);
// 设置头部和尾部的初始间距
CGFloat margin = collectionViewSize.width/2 - itemWidth/2;
self.sectionInset = UIEdgeInsetsMake(0, margin, 0, margin);
}