美文网首页iOS开发
iOS Collection View 编程指导(三)-如何使用

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

作者: 陵无山 | 来源:发表于2018-09-26 11:05 被阅读78次

    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更好点.

    相关文章

      网友评论

        本文标题:iOS Collection View 编程指导(三)-如何使用

        本文链接:https://www.haomeiwen.com/subject/oirdoftx.html