细说UICollectionView

封面.jpg

前言

你应该知道的,UICollectionViewUITableView都是继承于UISrollView,他们有很多相似的地方,所以你可以称他们为“双胞胎兄弟”。如果你使用过UITableView, 那下面的教程你会感觉到很熟悉。

以前,我们去做类似瀑布流这种效果的时候,必须把UITableView去旋转实现,从而显得很复杂。可喜的是,iOS6.0之后APPLE便推出了CollectionView,想想也是贴心呢。

UIColletionView基础

首先上图:本文就是来实现这图的结构:


图1.png

1.先来创建一个UIColletionView对象

         @property (nonatomic ,strong) UICollectionView *basicCollectionView;

         在.m文件里添加宏定义
         #define kScreenHeigth self.view.frame.size.height
         #define kScreenWidth  self.view.frame.size.width
         #define kRBG(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0  blue:b/255.0  alpha:1]
         #define basicBasicCollectionViewControllerCell @"basicBasicCollectionViewControllerCell"
  
         在@end上面添加下面get方法
         #pragma mark - GET
         //懒加载的方式去初始化UICollectionView对象
        - (UICollectionView *)basicCollectionView{
        if (!_basicCollectionView) 

        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

         //cell大小
        layout.itemSize = CGSizeMake(100, 50);

         //设置滑动的方向
        [layout setScrollDirection:UICollectionViewScrollDirectionVertical];

        //初始化
        _basicCollectionView = [[UICollectionView alloc] initWithFrame: CGRectMake(0, 0,kScreenWidth , kScreenHeigth -64) collectionViewLayout:layout];
        
         //签订协议
         _basicCollectionView.dataSource = self;
         _basicCollectionView.delegate   =self;
        //注册cell
        [_basicCollectionView registerClass:[UICollectionViewCell class]       forCellWithReuseIdentifier:basicBasicCollectionViewControllerCell];
          }
        return _basicCollectionView;
     }

2.在viewDidLoad最下面中加入

      [self.view addSubview:self.basicCollectionView];

PS:你在上面可以看到UICollectionViewFlowLayout这个类,这是个为UICollectionViewCell布局的类,这是和UITableView不同的地方,所以它比UITableView要更加灵活。

3.实现协议(这个和UITableView很像)


       #pragma mark - UIcollectionView dataSource
       - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView           *)collectionView{
       return 1;
       }

       - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
       return 10;
       }

       - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
       UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:basicBasicCollectionViewControllerCell forIndexPath:indexPath];
       cell.backgroundColor = kRBG(33, 52, 72);
       return cell;
       }

接下来可以运行了(效果如下:)

图2.png

3.现在我们来加入头视图和尾视图:

     1.首先添加宏定义
         #define  basicBasicCollectionViewControllerHeaderView @"UICollectionElementKindSectionHeader"
         #define  basicBasicCollectionViewControllerFooterView @"UICollectionElementKindSectionFooter"
     2.在get方法注册cell下面添加下面两行代码
     
        //注册头视图
        [_basicCollectionView registerClass:[UICollectionReusableView class]    forSupplementaryViewOfKind:basicBasicCollectionViewControllerHeaderView withReuseIdentifier:basicBasicCollectionViewControllerHeaderView];
        
        //注册尾视图
        [_basicCollectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:basicBasicCollectionViewControllerFooterView withReuseIdentifier:basicBasicCollectionViewControllerFooterView];

     3.添加dataSource方法
      

          /**
            *
            *
            *  @param collectionView
            *  @param kind            根据字符串分辨是是头视图或者尾视图
            *  @param indexPath
            *
            *  @return                返回头视图或者尾视图
            */
            - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
    
            UICollectionReusableView *reusableView = nil;
            if ([kind isEqualToString:basicBasicCollectionViewControllerFooterView]) {
            UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:basicBasicCollectionViewControllerFooterView withReuseIdentifier:basicBasicCollectionViewControllerFooterView forIndexPath:indexPath];
            view.backgroundColor = kRBG(58, 36, 63);
            reusableView = view;
        
        }else if ([kind isEqualToString:@"UICollectionElementKindSectionHeader"]) {
            UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:basicBasicCollectionViewControllerHeaderView withReuseIdentifier:basicBasicCollectionViewControllerHeaderView forIndexPath:indexPath];
            view.backgroundColor = kRBG(58, 36, 63);
            reusableView = view;
       }
            return reusableView;
    }


    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{
       return CGSizeMake(kScreenWidth, 60);
    }


    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
       return CGSizeMake(kScreenWidth, 60);
    }

   4.现在我们来设置图1中的top ,left ,bottom ,right。

    - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(20, 10, 20, 10);
    }

运行结果如下:


图3.png

5.单元格看起来太整齐,总觉得图一得放荡不羁要酷一些,添加一下代码在ViewController.m中:

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
       NSInteger randomHeigth = random()%70;
       NSInteger randomWidth = random()%100;
       return CGSizeMake(randomWidth +30, randomHeigth + 30);
    }

6.修改单元格的个数为20,效果图:

图4.png

以上就是就是一个简单的UICollectionView对象的结构图。

认识UICollectionViewLayout

我们先看看官方的描述:

The UICollectionViewFlowLayout class is a concrete layout object that organizes items into a grid with optional header and footer views for each section. The items in the collection view flow from one row or column (depending on the scrolling direction) to the next, with each row comprising as many cells as will fit. Cells can be the same sizes or different sizes.

UICollectionViewFlowLayout是一个为section管理单元格布局的具体对象,而且这个section有可能附带着头视图或者尾视图。这些在子视图排列的方向取决于collectionview滑动方向,而且单元格的大小可以是随机可控的。

The UICollectionViewLayout class is an abstract base class that you subclass and use to generate layout information for a collection view. The job of a layout object is to determine the placement of cells, supplementary views, and decoration views inside the collection view’s bounds and to report that information to the collection view when asked. The collection view then applies the provided layout information to the corresponding views so that they can be presented onscreen.

UICollectionViewLayout是一个抽象的基类,你能够子类化这个基类来为一个collectionview设计布局信息。这个布局对象的任务就是决定摆放单元格,头视图,尾视图的摆放位置以及响应对collectionview信息请求的回应。接下来,collectionview将提供相关的布局信息给相应的视图,让其显示在屏幕上。

接下来看看UICollectionViewLayout关于布局的方法:

//Returns the layout attributes for the item at the specified index path.(返回对应单元格路径的布局信息)
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

//Returns the layout attributes for all of the cells and views in the specified rectangle.(返回指定区域的所有单元格的布局信息容器)
- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

//Returns the width and height of the collection view’s contents.(返回内容所需要的长和宽,你可以理解为UIScrollView contentSize)
- (CGSize)collectionViewContentSize; 

如果你子类化一个UICollectionViewLayout对象,你会发现上面的方法是按顺序调用的。根据indexPath拿到每一个的布局信息,然后拿到所有的布局信息。根据所有的布局信息来计算需要显示内容的尺寸。

有时候你可能需要定义两种Layout方式,在一个collectionview视图里面进行布局的切换。使用下面的方法就可以很简单的完成你需要的操作。

// transition from one layout to another
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated; 

你可以很方便的使用collectionview来添加,删除数据和相应的动画,在改变数据后执行

- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;

collectionview需要添加和删除的时候,UICollectionViewLayout一样可以完成上述操作。特别是一个单元格被移动,添加或者是删除。你可以利用下面的API组合你完成你想要的动作和动画

- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems;

- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;

- (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;

- (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath;

- (void)finalizeCollectionViewUpdates;

更多了解您可以点击Demo。下面是demo效果:

demo.gif

参考资料:

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

推荐阅读更多精彩内容

  • 翻译自“Collection View Programming Guide for iOS” 0 关于iOS集合视...
    lakerszhy阅读 3,817评论 1 22
  • The UICollectionView class manages an ordered collection ...
    lixiaoshuai阅读 721评论 0 0
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 其实仔细想来,在我身边的朋友们大多是以男性为主,从事着传统的行业,靠出卖体力,时间来换取那一点点可悲的生活支出,虽...
    沐七月阅读 520评论 9 10
  • 水儿 无处不自在 遇方随方 遇圆就圆 哪哪安 他们说 水的心儿 真静啊
    雪莉诗话阅读 152评论 10 10