1.自定义一个继承自UICollectionViewFlowLayout的类
//
// LineLayout.h
// 自定义UICellectionView布局
//
#import <UIKit/UIKit.h>
@interface LineLayout : UICollectionViewFlowLayout
@end
//
// LineLayout.m
// 自定义UICellectionView布局
//
#import "LineLayout.h"
static const CGFloat ItemWH = 100;
@implementation LineLayout
/**
* 只要显示的边界发生改变就重新布局
* 内部就会重新调用layoutAttributesForElementsInRect方法获得cell布局属性
*/
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
/**
* 用来设置CollectionView停止滚动那一刻的位置(系统自动调用)
*
* @param proposedContentOffset 原本scrollView停止滚动那一刻的位置
* @param velocity 滚动速度
*/
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
//1.计算出CollectionView最后停留的范围
CGRect lastRect;
lastRect.origin = proposedContentOffset;
lastRect.size = self.collectionView.frame.size;
//2.计算屏幕最中间的x
CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width;
//3.取出这个范围内的所有属性
NSArray *array = [self layoutAttributesForElementsInRect:lastRect];
//4.遍历所有属性
CGFloat adjustOffsetX = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (ABS(attrs.center.x - centerX) < ABS(adjustOffsetX)) {
adjustOffsetX = attrs.center.x - centerX;
}
}
return CGPointMake(proposedContentOffset.x + adjustOffsetX, proposedContentOffset.y);
}
/**
* 一些初始化的工作最好在这里做
*/
- (void)prepareLayout
{
[super prepareLayout];
//每个cell的尺寸
self.itemSize = CGSizeMake(ItemWH, ItemWH);
CGFloat inset = (self.collectionView.frame.size.width - ItemWH) * 0.5;
self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
//设置水平滚动方向
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
//设置cell的间距(行距)
self.minimumInteritemSpacing = 100;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
//0.计算可见的矩形框
CGRect visiableRect;
visiableRect.size = self.collectionView.frame.size;
visiableRect.origin = self.collectionView.contentOffset;
//1.取得默认的cell的UICollectionViewLayoutAttributes
NSArray *array = [super layoutAttributesForElementsInRect:rect];
//2.计算屏幕最中间的x
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
//3.遍历所有属性
for (UICollectionViewLayoutAttributes *attrs in array) {
if (!CGRectIntersectsRect(visiableRect, attrs.frame)) continue;
//每一个item的中点x
CGFloat itemCenterX = attrs.center.x;
//根据屏幕最中间的距离计算缩放比例
CGFloat scale = 1 + 0.7 * (1 - ABS(itemCenterX - centerX) / self.collectionView.frame.size.width);
attrs.transform3D = CATransform3DMakeScale(scale, scale, 1.0);
}
return array;
}
@end
2.控制器里创建UICollectionView
//
// ViewController.m
// 自定义UICellectionView布局
//
#import "ViewController.h"
#import "ImageCell.h"
#import "LineLayout.h"
@interface ViewController () <UICollectionViewDataSource,UICollectionViewDelegate>
@property(nonatomic,strong)NSMutableArray *images;
@property(nonatomic,weak)UICollectionView *collectionView;
@end
@implementation ViewController
static NSString *const ID = @"image";
- (NSMutableArray *)images
{
if (!_images) {
self.images = [[NSMutableArray alloc] init];
for (int i=1; i<=20; i++) {
[self.images addObject:[NSString stringWithFormat:@"%d",i]];
}
}
return _images;
}
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建一个UICollectionView并添加到视图
CGFloat w = self.view.frame.size.width;
CGRect rect = CGRectMake(0, 100, w, 200);
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:[[LineLayout alloc] init]];
collectionView.backgroundColor = [UIColor orangeColor];
collectionView.delegate = self;
collectionView.dataSource = self;
[collectionView registerNib:[UINib nibWithNibName:@"ImageCell" bundle:nil] forCellWithReuseIdentifier:ID];
[self.view addSubview:collectionView];
self.collectionView = collectionView;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//改布局
if ([self.collectionView.collectionViewLayout isKindOfClass:[LineLayout class]]) {
[self.collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];
}else{
[self.collectionView setCollectionViewLayout:[[LineLayout alloc] init] animated:YES];
}
}
#pragma mark - UICollectionViewDataSource
/**
* 每组有多少个cell
*/
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.images.count;
}
/**
* 返回cell
*/
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
cell.image = self.images[indexPath.item];
return cell;
}
#pragma mark - UICollectionViewDelegate
/**
* 点击了cell
*/
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
//删掉一个cell
//1.删除模型数据
[self.images removeObjectAtIndex:indexPath.item];
//2.刷新UI
[collectionView deleteItemsAtIndexPaths:@[indexPath]];
}
@end
3.用到的自定义的UICollectionViewCell
//
// ImageCell.h
// 自定义UICellectionView布局
#import <UIKit/UIKit.h>
@interface ImageCell : UICollectionViewCell
@property(nonatomic,copy)NSString *image;
@end
//
// ImageCell.m
// 自定义UICellectionView布局
#import "ImageCell.h"
@interface ImageCell()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ImageCell
- (void)awakeFromNib
{
self.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
self.imageView.layer.borderWidth = 2;
self.imageView.layer.masksToBounds = YES;
self.imageView.layer.cornerRadius = 5;
}
- (void)setImage:(NSString *)image
{
_image = [image copy];
self.imageView.image = [UIImage imageNamed:image];
}
@end
4.ImageCell.xib