iOS UICollectionLayout 自定义

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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列出来作为例子。

 

以上是关于iOS UICollectionLayout 自定义的主要内容,如果未能解决你的问题,请参考以下文章

ios10自定手势有啥用

无法使用 Firebase 在 iOS 中接收自定义通知

Firebase 自定义声明 IOS 和 swift

IOS - 自定尺寸单元问题

ios 的 FCM 自定义通知

接收自定义通知 iOS swift 2.0