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列出来作为例子。

 

转载于:https://www.cnblogs.com/mdurant/p/5336585.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值