iOS 关于自定义UICollectionViewLayout实现复杂布局

2018/03/06 20:59
阅读数 20

UICollectionView的简单介绍

UICollectionView的结构

Cells
Supplementary Views 追加视图 (类似Header或者Footer)
Decoration Views 装饰视图 (用作背景展示)

由两个方面对UICollectionView进行支持

和tableView一样,即提供数据的UICollectionViewDataSource以及处理用户交互的UICollectionViewDelegate。

另一方面 对于cell的样式和组织方式,由于collectionView比tableView要复杂得多,因此没有按照类似于tableView的style的方式来定义,而是专门使用了一个类来对collectionView的布局和行为进行描述,这就是UICollectionViewLayout

而我们主要讲UICollectionViewLayout,因为这不仅是collectionView和tableView的最重要求的区别,也是整个UICollectionView的精髓所在

UICollectionViewLayoutAttributes类的介绍

一个UICollectionViewLayoutAttributes对象管理着一个Collection View中给定的一个Item的布局有关的属性。当被CollectionView要求时布局对象创建这个类的实例。

open class UICollectionViewLayoutAttributes : NSObject, NSCopying, UIDynamicItem {

    
    open var frame: CGRect item的位置

    open var center: CGPoint item的中心点 这个中心点是在给定的Collection View坐标系中的点。设置这个属性的值也会更新frame属性中的origin的值。

    open var size: CGSize item的大小

    open var transform3D: CATransform3D item的放射变化 使用你指定的放射变换赋值给这个属性替换transform3D属性的值

    @available(iOS 7.0, *)
    open var bounds: CGRect

    @available(iOS 7.0, *)
    open var transform: CGAffineTransform item在平面上的变化

    open var alpha: CGFloat item的透明度 0 - 1

    open var zIndex: Int // default is 0 item指定在Z轴上的位置 这个属性被用来确定在布局时Item的前后顺序。大的zIndex值的Item会被显示在小的zIndex值的Item上面。这个属性使用相同的值的Item的顺序是不确定的。
  这个属性的值默认为0
open var isHidden: Bool // As an optimization, UICollectionView might not create a view for items whose hidden attribute is YES open var indexPath: IndexPath Collection ViewItem的索引值。
  索引包含了一个Section的索引和一个Item在这个Section中的索引。这两个值标示在Collection View唯一的对应的Item的位置。 open var representedElementCategory: UICollectionElementCategory {
get } Item的类型。
  你可以使用这个属性的值来区分这个布局属性是用于一个Cell还是Supplementary View还是Decoration View。 open var representedElementKind: String
? { get } // nil when representedElementCategory is UICollectionElementCategoryCell
    目标视图的布局指定标识符。
    你可以使用这个属性的值来标识 Supplementary View或者 Decoration View相关联的 属性给定的目的。如果 representedElementCategory属性为 UICollectionElementCategoryCell,那么这个    属性为 nil
}
typedef NS_ENUM(NSUInteger, UICollectionElementCategory) {
    UICollectionElementCategoryCell, // Cell
    UICollectionElementCategorySupplementaryView, // Supplementary View
    UICollectionElementCategoryDecorationView // Decoration View
};

自定义UICollectionViewLayout

UICollectionViewLayout的功能是向UICollectionView提供布局信息 不仅包括cell的布局信息,也包括追加视图和装饰视图的布局信息。实现一个自定义layout的常规做法是继承UICollectionViewLayout类,然后重载下列方法:

准备方法被自动调用 以保证layout实例的正确 为即将进行的layout作前期的计算

open func prepare()

返回指定区域中的Cell和View的属性

返回的是包含UICollectionViewLayoutAttributes的数组  UICollectionViewLayoutAttributes可以是数组 追加视图(头尾视图)的信息

func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
返回对应于indexPath的位置的cell的布局属性
func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
返回对应于indexPath的位置的追加视图的布局属性,如果没有追加视图可不重载
创建并返回一个表示给定索引值对应的 Supplementary View的布局属性对象。
使用这个方法为 Collection View中的一个 Supplementary View创建一个布局属性对象。和 Cell一样, Supplementary View当前的数据是被 Collection View数据源所管理的。但是和 Cell不同的是, Supplementary View通常是为特殊目的而设计的。例如, HeaderFooterCell的放置位置不同,是提供给在单个的 Section或者整个 Collection View的。
由你来决定如何使用 indexPath参数来识别一个给定的 Supplementary View。通常,你使用 elementKind属性来确定 Supplementary View的类型,然后使用 indexPath的信息来识别不同 Supplementary View实例。
func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
创建并返回一个表示给定索引值对应的 Decoration View的布局属性对象。
使用这个方法为 Collection View中的一个 Decoration View创建一个布局属性对象。 Decoration ViewSupplementary View的一种,但是不会展示被 Collection View数据源所管理的数据。相反,它们大多数为一个 Section或者整个 Collection View呈现视觉装饰效果。
由你来决定如何使用 indexPath参数来识别一个给定的 Decoration View。通常,你使用 decorationViewKind属性来确定 Decoration View的类型,然后使用 indexPath的信息来识别不同 Decoration View实例。
func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?

当边界发生改变的时候 是否应该刷新布局 如果YES则在边界变化(一般是scroll到其他地方)时,将重新计算需要的布局信息。

func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool

方法的调用顺序

1)-(void)prepareLayout  设置layout的结构和初始需要的参数等。

2)  -(CGSize) collectionViewContentSize 确定collectionView的所有内容的尺寸。

3)-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect初始的layout的外观将由该方法返回的UICollectionViewLayoutAttributes来决定。

4)在需要更新layout时,需要给当前layout发送 
     1)-invalidateLayout, 该消息会立即返回,并且预约在下一个loop的时候刷新当前layout
     2)-prepareLayout,
     3)依次再调用-collectionViewContentSize和-layoutAttributesForElementsInRect来生成更新后的布局。

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部