(修正)分享一个卡片式布局的collectionView

老规矩,先看效果图

QQ20170817-152627.gif
第一步,自定义ZLFlowLayout继承于UICollectionViewFlowLayout

具体代码:

#import "ZLFlowLayout.h"
#import "ZLFlowLayoutConstants.h"

@implementation ZLFlowLayout


- (instancetype)init
{
    self = [super init];
    if (self)
    {
        self.minimumLineSpacing = 15.0f;
        self.itemSize = CGSizeMake(SCREEN_WIDTH - LEFT_OFFSET*2, (SCREEN_WIDTH - LEFT_OFFSET*2)/0.618f);
        self.scrollDirection = UICollectionViewScrollDirectionHorizontal;//设置为水平滑动
        self.sectionInset = UIEdgeInsetsMake(64, LEFT_OFFSET, 0, LEFT_OFFSET);
    }
    return self;
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)oldBounds
{
    return YES;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray * array = [[NSArray alloc]initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];
    CGRect visiableRect;
    visiableRect.origin = self.collectionView.contentOffset;
    visiableRect.size = self.collectionView.bounds.size;

    for (UICollectionViewLayoutAttributes * attributes in array)
    {
        if (CGRectIntersectsRect(attributes.frame, rect))
        {
            CGFloat distance = CGRectGetMidX(visiableRect) - attributes.center.x;
            distance = ABS(distance);
            if (distance < SCREEN_WIDTH/2 + self.itemSize.width)
            {
                CGFloat zoom = 1 + ITEM_ZOOM * (1 - distance/THE_ACTIVE_DISTANCE);
                attributes.transform3D = CATransform3DMakeScale(zoom, zoom, 1.0f);
                attributes.transform3D = CATransform3DTranslate(attributes.transform3D, 0, -zoom * 25, 0);
                attributes.alpha = zoom - ITEM_ZOOM;
            }
        }
    }
    return array;
}

- (CGPoint )targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
    CGFloat offsetAdjustment = MAXFLOAT;
    CGFloat horizontalCenter_X = proposedContentOffset.x + CGRectGetWidth(self.collectionView.bounds)/2.0;
    CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
    NSArray *array = [super layoutAttributesForElementsInRect:targetRect];
    for (UICollectionViewLayoutAttributes * attributes in array)
    {
        CGFloat itemHorizontalCenter_X = attributes.center.x;
        if (ABS(itemHorizontalCenter_X - horizontalCenter_X) < ABS(offsetAdjustment))
        {
            offsetAdjustment = itemHorizontalCenter_X - horizontalCenter_X;
        }
    }
    return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}
第二步,创建collectionView
#import "ZLCollectionView.h"
#import "ZLFlowLayout.h"

static NSString * identifier = @"collecitonView_cell";
@interface ZLCollectionView ()<UICollectionViewDelegate,UICollectionViewDataSource>

@property (nonatomic,strong) UICollectionView *mainCollectionView;
@property (nonatomic,assign) NSInteger itemCount;
@property (nonatomic,assign) CGRect collectionViewFrame;

@end

@implementation ZLCollectionView


+ (instancetype)collectionViewWithFrame:(CGRect)frame itemCount:(NSInteger)itemCount
{
    return [[self alloc]initWithFrame:frame itemCount:itemCount];
}

- (instancetype)initWithFrame:(CGRect)frame itemCount:(NSInteger)itemCount
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.itemCount = itemCount;
        self.collectionViewFrame = frame;
        [self createCollectionViewStyle];
    }
    return self;
}


- (void)createCollectionViewStyle
{
    ZLFlowLayout *layout = [[ZLFlowLayout alloc]init];
    self.mainCollectionView = [[UICollectionView alloc]initWithFrame:self.collectionViewFrame collectionViewLayout:layout];
    self.mainCollectionView.delegate = self;
    self.mainCollectionView.dataSource = self;
    self.mainCollectionView.backgroundColor = [UIColor groupTableViewBackgroundColor];
    self.mainCollectionView.showsHorizontalScrollIndicator = NO;
    [self addSubview:self.mainCollectionView];

    NSLog(@"%f -- %f",layout.itemSize.width,layout.itemSize.height); //375.404


    //注册cell
    [self.mainCollectionView registerClass:[UICollectionViewCell class]
                forCellWithReuseIdentifier:identifier];
}

- (NSInteger )numberOfItemsInSection:(NSInteger)section
{
    return 1;
}
- (NSInteger )collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.itemCount;
}
- (__kindof CustomCollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CustomCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier
                                                                           forIndexPath:indexPath];

    /*这段代码的作用就是:
     *当直接往细胞上面添加视图内容时,随着滑动,可能会出现内容重叠的问题。
     *但是在自定义细胞时使用这段代码,就会移除细胞的所有子视图,
     *使用Masonry给电池子视图上的内容进行约束就会崩溃,或者直接给细胞上的内容进行约束时就会出现细胞显示而上面内容不显示的问题。
    //这一步,防止cell上面的内容发生重叠
    for (UIView * view in cell.subviews)
    {
        [view removeFromSuperview];
    }
     */

    cell.backgroundColor = [UIColor lightGrayColor];
    cell.layer.masksToBounds = YES;
    cell.layer.cornerRadius = 5.0f;

    
    NSLog(@"Cell:%f--%f",cell.frame.size.width,cell.frame.size.height);
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    self.selectedItems(indexPath);
}

- (void)didSelectedItemsWithBlock:(DidSelectedItems)selectedItems
{
    self.selectedItems = selectedItems;
}
@end
第三步、使用
ZLCollectionView *collectionView = [ZLCollectionView collectionViewWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) itemCount:30];
[collectionView didSelectedItemsWithBlock:^(NSIndexPath *indexPath) {
   NSLog(@"ItemTag:%ld",indexPath.item);
}];
[self.view addSubview:collectionView];

说明

可以通过修改ZLFlowLayoutConstants.hITEM_ZOOMTHE_ACTIVE_DISTANCELEFT_OFFSET的值,来修改卡片item的大小样式

之前会一直遇到这个警告提示

2017-08-17 16:18:17.133324+0800 ZLCollectionViewFlowLayout[4342:480201] Logging only once for UICollectionViewFlowLayout cache mismatched frame
2017-08-17 16:18:17.133680+0800 ZLCollectionViewFlowLayout[4342:480201] UICollectionViewFlowLayout has cached frame mismatch for index path <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0} - cached value: {{55, 86.346884732472063}, {210, 339.80584123617336}}; expected value: {{60, 122}, {200, 323.62461070111749}}
2017-08-17 16:18:17.133859+0800 ZLCollectionViewFlowLayout[4342:480201] This is likely occurring because the flow layout subclass ZLFlowLayout is modifying attributes returned by UICollectionViewFlowLayout without copying them

后来百度了一下,将layoutAttributesForElementsInRect中的NSArray * array = [super layoutAttributesForElementsInRect:rect];换成NSArray * array = [[NSArray alloc]initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];就解决了。

这是我的github地址,有喜欢的可以star一下,谢谢了。

=======================================================================================================

更正

2017-11-24
=======================================================================================================

之前有小伙伴私信问起使用Masonry自定义cell,会出现-崩溃-或者-内容显示不出来但cell能显示-的问题,把ZLCollectionView.m中的下面一段代码注释了就行。

//这一步,防止cell上面的内容发生重叠
    for (UIView * view in cell.subviews)
    {
        [view removeFromSuperview];
    }

这段代码的作用就是:

当直接往cell上面添加视图内容时,随着滑动,可能会出现内容重叠的问题。但是在自定义cell时使用这段代码,就会移除cell的所有子视图,使用Masonry给cell子视图上的内容进行约束就会崩溃,或者直接给cell上的内容进行约束时就会出现cell显示而上面内容不显示的问题。

我修改一下demo,标注了这个问题,添加了自定义cell的内容,有需要的小伙伴可以去我github下载一下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349