UICollectionView总结

简介

UICollectionView的强大之处:灵动的布局。结合动力学、交互转场、layout对象可以创造布局的无限可能。

其核心就是和UICollectionViewLayout对象的配合

UICollectionViewLayout介绍

管理布局信息,供UICV使用

基本功能
  • 使布局无效或指定某个环境的布局无效,以便将来重新布局
    public func invalidateLayout()
    public func invalidateLayoutWithContext(context:  UICollectionViewLayoutInvalidationContext)
  • 添加装饰视图,不依赖UICollectionViewDataSource。牛!
public func registerClass(viewClass: AnyClass?, forDecorationViewOfKind elementKind: String)
public func registerNib(nib: UINib?, forDecorationViewOfKind elementKind: String)
  • 通过重写如下方法提供自定义的布局属性对象UICollectionViewLayoutAttributes和布局无效的环境对象
public class func layoutAttributesClass() -> AnyClass 
public class func invalidationContextClass() -> AnyClass 
  • 准备布局。这个方法用于提高流畅度
    这是特别重要的方法,提供预处理环境。可以在这里更新数据结构和做复杂的计算。
public func prepareLayout()
  • 为UICV提供布局属性对象UICollectionViewLayoutAttributes
    这里有必须实现的方法,如果有装饰/补充视图那么以下方法都要实现。这些方法是最基础也是最重要的。
public func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? 

public func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?

public func layoutAttributesForSupplementaryViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?

public func layoutAttributesForDecorationViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
  • 根据Bounds的改变来确定是否使layout或UICollectionViewLayoutInvalidationContext对象无效
public func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool 

public func invalidationContextForBoundsChange(newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext
  • iOS8.0 cell有方法改变布局对象提供的布局信息,也就是自己提供布局信息。这里提供方法让cell自己提供的布局信息preferredAttributes无效。
    @available(iOS 8.0, *)
    public func shouldInvalidateLayoutForPreferredLayoutAttributes(preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> Bool

    @available(iOS 8.0, *)
    public func invalidationContextForPreferredLayoutAttributes(preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutInvalidationContext
  • 提供滚动停止点,用户获取这个点来做自己想做的事
public func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint

public func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint) -> CGPoint 
  • 内容尺寸,子类必须实现
public func collectionViewContentSize() -> CGSize
编辑更新功能
  • 当item被编辑(删除、添加等)或者bounds被改变,会调用以下方法
    这里的调用顺序是先于initial / final方法的,详见后面的方法。
public func prepareForCollectionViewUpdates(updateItems: [UICollectionViewUpdateItem])
public func finalizeCollectionViewUpdates() 

public func prepareForAnimatedBoundsChange(oldBounds: CGRect) 
public func finalizeAnimatedBoundsChange()
  • 被编辑item的布局属性更新
    This set of methods is called when the collection view undergoes an animated transition such as a batch update block or an animated bounds change.

    • 出现动画:initialLayoutAttributesForAppearingItemAtIndexPath获取对应indexPath的刚出现时最初布局->更新后布局变化过程
    • 消失动画:更新之前的布局 ->finalLayoutAttributesForDisappearingItemAtIndexPath方法获取对应indexPath的消失时最终布局的变化过程
    public func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
    public func finalLayoutAttributesForDisappearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?

    public func initialLayoutAttributesForAppearingSupplementaryElementOfKind(elementKind: String, atIndexPath elementIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
    public func finalLayoutAttributesForDisappearingSupplementaryElementOfKind(elementKind: String, atIndexPath elementIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
    public func initialLayoutAttributesForAppearingDecorationElementOfKind(elementKind: String, atIndexPath decorationIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
    public func finalLayoutAttributesForDisappearingDecorationElementOfKind(elementKind: String, atIndexPath decorationIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
关键知识点
  • Supplementary views 并不一定会作为 header 或 footer view;他们的数量和放置的位置完全由布局控制
  • Decoration views 纯粹为一个装饰品。他们完全属于布局对象,并被布局对象管理,他们并不从 data source 获取的 contents
  • collection view 布局

    • 独立于内容的布局

      这正是你所知道的像 UITableView 和 UICollectionViewFlowLayout 这些情况。每个 cell 的位置和外观不是基于其显示的内容,但所有 cell 的显示顺序是基于内容的顺序。可以把默认的 flow layout 做为例子。每个 cell 都基于前一个 cell 放置(或者如果没有足够的空间,则从下一行开始)。布局对象不必访问实际数据来计算布局。

    • 基于内容的布局

      在很多情况下,布局对象不仅需要取出当前可见 cell 的数据,还需要从所有记录中取出一些决定当前哪些 cell 可见的数据。如果有一个依赖内容的布局,那就是暗示你需要写自定义的布局类了,同时不能使用自定义的 UICollectionViewFlowLayout,所以这正是我们需要做的事情。

  • 性能是必须考虑的因素

  • layoutAttributesForElementsInRect在可见范围内返回布局属性,不要全部返回,会影响性能
  • shouldInvalidateLayoutForBoundsChange

    最后,当 collection view 的 bounds 改变时,布局需要告诉 collection view 是否需要重新计算布局。我的猜想是:当 collection view 改变大小时,大多数布局会被作废,比如设备旋转的时候。因此,一个幼稚的实现可能只会简单的返回 YES。虽然实现功能很重要,但是 scroll view 的 bounds 在滚动时也会改变,这意味着你的布局每秒会被丢弃多次。根据计算的复杂性判断,这将会对性能产生很大的影响

  • prepareForCollectionViewUpdates跟踪更新对象,可以进行跟踪是件很酷的事情。

感悟

职责分明是写一个好框架的必要前提,当所有事情分配的井然有序,那么离成功也就不远了。我们要做的就是对职责的规划和抽离,站在高处看清问题的本质。

相关网址

UICollectionView动画
objccn.io Collection View 动画
自定义布局
UICollectionView + UIKit 力学

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值