iOS Collection View 编程指导(三)-如何使用Flow Layout

UICollectionViewFlowLayout类来管理collectionView中的布局, 它是一个具体的类, 可以直接使用. flow layout实现了一种基于线性的断裂式布局, 也就是说collectionView中的item是按照线性顺序排列的, 该布局会尽量适配item的间距, 使得item排列在同一行, 如果超出一行会接着进行下一行的排列. 图3-1展示了水平方向上的flow layout.

图3-1 使用flow layout布局section和cell

使用flow layout除了可以实现一个网格状的collectionView, 还可以实现更多样式. 比如, 你可以调整间距来实现一个单行滚动的collectionView. 如果item的size可以不同, 这样可以产生非对称效果. 你可以通过代码和xib来配置你的flow layout对象, 步骤如下:

  • 创建一个flow layout对象, 将其赋值给collectionView
  • 设置cell的width和height
  • 设置行间距, item的间距
  • 如果你想要section header和footer, 给footer和header设置size
  • 设置flow layout滚动的方向(scroll layout)

注意:配置layout时, 你至少需要配置cell的宽高, 不然item默认的宽高为0, 导致item不可见

自定义Flow Layout Attributes


flow layout对象暴露了几个属性用于配置item的外观, 当你设置这些属性时, 该属性对所有的item都有起作用. 比如你通过属性itemSize来配置item的大小后, 所有的item大小都和属性中配置的一样.

如果你想item的size和spacing都不一样, 那么你需要实现flow layout的委托UICollectionViewDelegateFlowLayout. 你可以将collectionView的delegate和flow layout的delegate设置成同一个. 当flow layout的delegate实现了相应的方法后, layout对象根据你实现的方法中返回的值来设置item的size和spacing.

设置item的size

  • 如果collectionView中的cell大小相同, 那么flow layout中的item的size大小可以通过itemSize来确定.
  • 如果item的size要不同, 那么需要实现委托方法collectionView:layout:sizeForItemAtIndexPath:来确定不同item的size. 在委托方法中, 你可以根据index path来确定不同item, 从而确定特定item的size. 如图3-2展示了不同item的不同size
图3-2 flow layout中的不同itemSize

注意:如果item的size是不同的, 那么会导致不同行的item的数量不同

设置行间距和itme的间距

  • 使用flow layout布局时, 你可以设置item间的最小间距, 以及最小行间距. 需要注意, 是最小间距, 而不是具体的间距, 也就是说实际显示的间距可能和你设置最小间距不同, 有可能大于最小间距.
  • 在布局时, flow layout往一行中加item, 直到一行显示不下, 才开始第二行. 如果一行刚好可以显示整数个item没有额外的空间, 那么此时item的间距为最小间距. 若果还有额外的空间, 那么layout对象会将item的间距均匀地调大以刚好适配屏幕. 如图3-3所展示调整itme的间距来避免最后留下大块空间
图3-3 item的实际间距大于最小间距
  • 对于行间距, flow layout使用同样原理来管理. 而且当item的size不同时, 导致行间距也不同. 行间距的实际距离和相邻两行中最大的两个item有关, 如图3-4所示


    图3-4 不同itemSize时的行间距
  • flow layout提供两个属性minimumLineSpacingminimumInterItemSpacing来设置静态的行间距和item间距, 如果想动态提供行间距和item间距可以使用委托方法collectionView:layout:minimumLineSpacingForSectionAtIndex:collectionView:layout:minimumInteritemSpacingForSectionAtIndex:来提供动态的间距.

使用Section Insets来调节section的margin

section inset是调节cells使用空间的一种手段. 你可以在section的左右, header/footer上下之间插入间距达到调节cell布局的空间大小. 如图3-5所示, 展示section inset的作用.


图3-5 section inset调节cell的可用空间

什么时候使用子类化的Flow Layout


在有的情况下, 使用UICollectionViewFlowLayout满足不了需求, 需要继承UICollectionViewFlowLayout做一些定制化的操作才行. 下面列举了使用子类化UICollectionViewFlowLayout的几种情况:

  • 给你的布局添加新的补充视图(supplementary)和装饰视图(decoration)

    标准的flow layout只提供了header, footer没有decoration view, 为了支持更多的supplementary和decoration view你需要重写下面的一些方法:

    • layoutAttributesForElementsInRect:(required)
    • layoutAttributesForItemAtIndexPath:(required)
    • layoutAttributesForSupplementaryViewOfKind:atIndexPath:(为了支持新的supplementary视图)
    • layoutAttributesForDecorationViewOfKind:atIndexPath:(为了支持新的decoration视图)
      layoutAttributesForElementsInRect:方法中, 需要调用父类方法来获得cell的layout attribute对象, 然后再添加supplementary或者decoration的layout attribute对象. 再使用其他方法来提供其他attribute. 关于如何创建layout attribute请看Creating Layout Attributes
  • 给flow layout返回的layout attribute对象做点调整

    重写layoutAttributesForElementsInRect:方法以及其他返回layout attribute对象的方法. 在这些方法中你应该调用super来获取attribute对象, 在方法中修改调用super获取layout attribute对象, 然后返回.

  • 给cell和其他view替换新的layout attribute对象

    • 通过集成UICollectionViewLayoutAttributes类, 自定义layout attribute对象, 你可以往layout attribute中添加新的特性(属性).
    • 然后在UICollectionViewFlowLayout的子类重写layoutAttributesClass方法返回你自定义的UICollectionViewLayoutAttributes的子类.
    • 你还应该重写layoutAttributesForElementsInRect:,layoutAttributesForItemAtIndexPath:方法, 在这些方法中你要给新的layout attribute对象中属性赋值.
  • 插入/删除的item, 确定item的initial/final位置

    默认情况下, 当你插入/删除cell时, 只有一个fade动画, 如果你想要自定义动画, 可以重写下面的方法:

    • initialLayoutAttributesForAppearingItemAtIndexPath:
    • initialLayoutAttributesForAppearingSupplementaryElementOfKind:atIndexPath:
    • initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath:
    • finalLayoutAttributesForDisappearingItemAtIndexPath:
    • finalLayoutAttributesForDisappearingSupplementaryElementOfKind:atIndexPath:
    • finalLayoutAttributesForDisappearingDecorationElementOfKind:atIndexPath:
      在cell被插入/删除前, 你可以通过上面的方法来设置特定的layout attribute对象, 然后flow layout会使用这些attribute来进行动画. 如果你重写了这些方法, Apple推荐你也重写prepareForCollectionViewUpdates:finalizeCollectionViewUpdates这两个方法. 你可以使用者两个方法来跟踪当前周期内那个item被插入/删除. 想知道关于删除/插入的工作原理, 请看Making Insertion and Deletion Animations More Interesting

上面的几种情况和操作也适用于创建自定义的layout, 不过在自定义layout之前考虑一下是否可以使用子类化的flow layout, 如果可以的话, 建议优先使用flow layout的子类, 因为flow layout是经过苹果精心设计的, 效果更好. 事实上, 需要用到自定义layout的情况很少, 因为使用flow layout或继承flow layout可以满足大多数需求. 只有少数情况下才需要自定义layout, 比如, 你的布局不是基于线性的, 或者你的内容不局限在屏幕两个方向上滚动, 你布局中的item经常移动, 在这些情况下用自定义layout更好点.

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

推荐阅读更多精彩内容