自定义UICollectionView格局-线性布局
自定义UICollectionView布局-线性布局
线性布局
上一节讲解了自定义布局的基本实现思路,这一节主要用自定义布局实现线性布局,做一个简单的图片浏览器效果。
自定义布局类
1. 自定义布局类
/// 继承自UICollectionViewFlowLayout,是因为流水布局有左右滚动的功能
@interface CYLineLayout : UICollectionViewFlowLayout
@end
2. 重新父类的方法
2.1 准备布局
/// 准备操作 一般在这里设置一些初始化参数
- (void)prepareLayout
{
// 必须要调用父类(父类也有一些准备操作)
[super prepareLayout];
CGFloat width = self.collectionView.frame.size.height * 0.7;
self.itemSize = CGSizeMake(width, width);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.minimumLineSpacing = 20;
// 设置内边距
CGFloat inset = (self.collectionView.frame.size.width - width) * 0.5;
self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
}
2.2 返回collectionView上面所有元素(比如cell)的布局属性
///
/// 返回collectionView上面所有元素(比如cell)的布局属性:这个方法决定了cell怎么排布
/// 每个cell都有自己对应的布局属性:UICollectionViewLayoutAttributes
/// 要求返回的数组中装着UICollectionViewLayoutAttributes对象
///
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 计算 CollectionView 的中点
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
for (UICollectionViewLayoutAttributes *attrs in array)
{
// 计算 cell 中点的 x 值 与 centerX 的差值
CGFloat delta = ABS(centerX - attrs.center.x);
CGFloat scale = 1 - delta / self.collectionView.frame.size.width;
attrs.transform = CGAffineTransformMakeScale(scale, scale);
}
return array;
}
2.3 当uicollectionView的bounds发生改变时,是否要刷新布局
/// 当uicollectionView的bounds发生改变时,是否要刷新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
2.4 返回collectionView最终的偏移量(最终的停留位置)
/// targetContentOffset :通过修改后,collectionView最终的contentOffset(取决定情况)
///
/// proposedContentOffset :默认情况下,collectionView最终的contentOffset
/// @param velocity 速率
///
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// NSLog(@"%@",NSStringFromCGPoint(proposedContentOffset));
CGSize size = self.collectionView.frame.size;
// 计算可见区域的面积
CGRect rect = CGRectMake(proposedContentOffset.x, proposedContentOffset.y, size.width, size.height);
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 计算 CollectionView 中点值
CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;
// 标记 cell 的中点与 UICollectionView 中点最小的间距
CGFloat minDetal = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attrs in array)
{
if (ABS(minDetal) > ABS(centerX - attrs.center.x))
{
minDetal = attrs.center.x - centerX;
}
}
return CGPointMake(proposedContentOffset.x + minDetal, proposedContentOffset.y);
}
3. 控制器使用布局
3.1 导入头文件
#import "CYLineLayout.h"
3.2 实例化布局
CYLineLayout *layout = [[CYLineLayout alloc]init]; // 线性布局
UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:frame collectionViewLayout:layout];
3.3 UICollectionView的数据源方法
// ……