zoukankan      html  css  js  c++  java
  • iOS 关于自定义UICollectionViewLayout实现复杂布局

    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来生成更新后的布局。
  • 相关阅读:
    case1.将文件夹内文件,按文件后缀不同进行分类
    openpyxl/csv--python处理excel表格模块
    pyttsx3--文字转语音库
    网络爬虫遵守规则
    python-requests库
    js 对象遍历出现的异常
    POI解析word文件,并为特定规则的key替换值
    bootstrap-table获得页面加载数据
    Javaweb项目下载文件时设置文件名
    MySQL自定义函数
  • 原文地址:https://www.cnblogs.com/huanying2000/p/8515272.html
Copyright © 2011-2022 走看看