zoukankan      html  css  js  c++  java
  • iOS UICollectionLayout 自定义

    前言

    一般有两种类型的 collection view 布局:

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

    2.基于内容的布局计算。我们的日历视图正是这样类型的例子。为了计算显示事件的起始和结束时间,布局对象需要 直接访问 collection view 的数据源。在很多情况下,布局对象不仅需要取出当前可见 cell 的数据,还需要从所有记录中取出一些决定当前哪些 cell 可见的数据。

    (以上摘自objc中国的一篇文章)

    仔细思考之后,我发现自定义flowlayout满足不了我的需求,所以选择2的方式,通过自定义layout来解决需求


     基于系统layout自定义一个,如下

    @interface xxxLayout : UICollectionViewLayout
    

    .m里主要的三个方法是如下

    A- (void)prepareLayout;  //  这个其实可以省,实现可以写去第三个里面
    B- (CGSize)collectionViewContentSize;
    C-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

    - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;  // 草率的话,这里返回yes就可以了。具体是个告诉layout要不要重新布局的方法

     前两个字面理解就是他的用处,第三个比较费解,其实就是return一个存了UICollectionViewLayoutAttributes对象的数组,

    UICollectionViewLayoutAttributes对象更费解,其实直译过来就可以知道,就是告诉布局对象如何布局的东西,当然知道以下三个方法就彻底明白了

    1- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
    2- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind 
    atIndexPath:(NSIndexPath *)indexPath; 3- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind
    atIndexPath:(NSIndexPath *)indexPath;

     以上三个方法点进-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;就能看到,就在这个下面

    到目前,虽然没有任何实现,先梳理以下流程。大致就是 A写算法,B写collectionView的区间,C写cell,supplementary view的实现,而123是根据需求创建,创建123的对象之后,可以给他们一些属性定义,然后存一个数组,让C返回

    以上是一些逻辑,看不懂也没事,下面是简单的实现。

    - (CGSize)collectionViewContentSize {
        CGFloat contentWidth = self.collectionView.bounds.size.width;
        CGFloat contentHeight = self.collectionView.bounds.size.height;
        
        CGSize contentSize = CGSizeMake(contentWidth, contentHeight);
        
        return contentSize;  //  给collectionView一个contentsize而已
    }
    
    //  self.attributeArray是我写的一个nsarray的属性,存UICollectionViewLayoutAttributes对象而已
    -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ NSIndexPath *indexPath = [NSIndexPath indexPathWithIndex:0];  
    //  现在没有表头什么的概念,因为都是自定义的,我只要section=0的位置一个表头就这样写他的位置 UICollectionViewLayoutAttributes *supplementaryViewAttributes =
    [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; [self.attributeArray addObject:supplementaryViewAttributes]; return self.attributeArray; } - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { //看清楚,这个是类方法,和123不一样
    UICollectionViewLayoutAttributes *attributes =
    [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath];   if ([elementKind isEqualToString:UICollectionElementKindSectionHeader]) { attributes.frame = CGRectMake(0, 0, kWidth, 50); } return attributes; }

     到这里,你的界面应该就有了一个表头了,去collectionView里,和往常一样,写datasource和delegate方法吧

    如果要cell的话,就是调用1,我这里仅仅把2列出来作为例子。

  • 相关阅读:
    [Android 4.4.4] 泛泰A850 三版通刷 Mokee4.4.4 KTU84P 20140626 RC2.2 by syhost
    YUV12(420) (from)to RGB24
    Python图像处理(16):图像金字塔
    内存管理笔记(分页,分段,逻辑地址,物理地址)【转】
    Linux内核分析--内核中的数据结构双向链表【转】
    标准IO与文件IO 的区别【转】
    Linux中设备号及设备文件【转】
    静态编译和动态编译的区别【转】
    嵌入式系统 Boot Loader 技术内幕【转】
    理解 Linux 的硬链接与软链接【转】
  • 原文地址:https://www.cnblogs.com/mdurant/p/5336585.html
Copyright © 2011-2022 走看看