整理 collectionView 水平自定义布局

来源:互联网 发布:狼群算法源代码 编辑:程序博客网 时间:2024/05/22 14:36

整理 collectionView 水平自定义布局
viewcontroll.h
@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate>@property (nonatomic, strong) NSMutableArray *images;@property (nonatomic, weak) UICollectionView *collectionView;@end@implementation ViewControllerstatic 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];        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.dataSource = self;    collectionView.delegate = self;    [collectionView registerNib:[UINib nibWithNibName:@"ImageCell" bundle:nil] forCellWithReuseIdentifier:ID];    [self.view addSubview:collectionView];    self.collectionView = collectionView;    // collectionViewLayout :    // UICollectionViewLayout    // UICollectionViewFlowLayout}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    if ([self.collectionView.collectionViewLayout isKindOfClass:[HMLineLayout class]]) {        [self.collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];    } else {        [self.collectionView setCollectionViewLayout:[[HMLineLayout alloc] init] animated:YES];    }}#pragma mark - <UICollectionViewDataSource>- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{    return self.images.count;}- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{    HMImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];    cell.image = self.images[indexPath.item];    return cell;}- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{    // 删除模型数据    [self.images removeObjectAtIndex:indexPath.item];        // 删UI(刷新UI)    [collectionView deleteItemsAtIndexPaths:@[indexPath]];}@end

<pre name="code" class="objc">lineLayout.m

static const CGFloat HMItemWH = 100;@implementation Layout- (instancetype)init{    if (self = [super init]) {    }    return self;}/** *  只要显示的边界发生改变就重新布局: 内部会重新调用prepareLayout和layoutAttributesForElementsInRect方法获得所有cell的布局属性 */- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{    return YES;}/** *  用来设置collectionView停止滚动那一刻的位置 * *  @param proposedContentOffset 原本collectionView停止滚动那一刻的位置 *  @param velocity              滚动速度 */- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{    // 1.计算出scrollView最后会停留的范围    CGRect lastRect;    lastRect.origin = proposedContentOffset;    lastRect.size = self.collectionView.frame.size;        // 计算屏幕最中间的x    CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;        // 2.取出这个范围内的所有属性    NSArray *array = [self layoutAttributesForElementsInRect:lastRect];        // 3.遍历所有属性    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(HMItemWH, HMItemWH);    CGFloat inset = (self.collectionView.frame.size.width - HMItemWH) * 0.5;    self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);    // 设置水平滚动    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;    self.minimumLineSpacing = HMItemWH * 0.7;        // 每一个cell(item)都有自己的UICollectionViewLayoutAttributes    // 每一个indexPath都有自己的UICollectionViewLayoutAttributes}/** 有效距离:当item的中间x距离屏幕的中间x在HMActiveDistance以内,才会开始放大, 其它情况都是缩小 */static CGFloat const HMActiveDistance = 150;/** 缩放因素: 值越大, item就会越大 */static CGFloat const HMScaleFactor = 0.6;- (NSArray *)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];    // 计算屏幕最中间的x    CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;        // 2.遍历所有的布局属性    for (UICollectionViewLayoutAttributes *attrs in array) {        // 如果不在屏幕上,直接跳过        if (!CGRectIntersectsRect(visiableRect, attrs.frame)) continue;                // 每一个item的中点x        CGFloat itemCenterX = attrs.center.x;                // 差距越小, 缩放比例越大        // 根据跟屏幕最中间的距离计算缩放比例        CGFloat scale = 1 + HMScaleFactor * (1 - (ABS(itemCenterX - centerX) / HMActiveDistance));        attrs.transform = CGAffineTransformMakeScale(scale, scale);    }        return array;}@end


0 0
原创粉丝点击