博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解读自定义UICollectionViewLayout--感动了我自己
阅读量:6160 次
发布时间:2019-06-21

本文共 7221 字,大约阅读时间需要 24 分钟。

  本文主要介绍了如何自定义UICollectionViewLayout。

    一、简介UICollectionView的布局

  首先我们回顾一下跟UICollectionView的几个类,看图说话。

  简单解释上图,UICollectionView有个属性是collectionViewLayout,这个属性就是用来描述collectionView中的控件布局的,一般在初始化UICollectionView的时候,我们会传入一个UICollectionViewLayout对象来描述布局信息。常见的UICollectionViewFlowLayout (流水布局)太简单,本文就不赘述了,只需要知道它是官方提供的一个布局特例(好多布局信息都为我们写好了),继承自UICollectionViewLayout。其实,真正描述UICollectionView中cell等位置的是进一步封装在UICollectionViewLayout中的UICollectionViewLayoutAttributes(布局属性),attributes对象中包含了索要描述的控件的位置,大小,透明度,层级等信息。UICollectionViewLayout会把描述各个控件的attributes对象,封装到一个数组里面去,统一返回给collectionView,告诉collectionView就按照这个“说明书”来布局。

  知道了这个关系,重点就是 自定义一个 UICollectionViewLayout 类,然后赋值给collectionView.collectionViewLayout。

  补充下,collectionView的组成元素:

  1、cell

  2、header 、footer(统称SupplementaryView)

  3、decorationView ,装饰,空间层次关系:在collectionView的背景之上,cell之下的一个视图,ibooks里面的那个书架就是它

   

  二、自定义UICollectionViewLayout

  首先建一个类继承自 UICollectionViewLayout,对了,每个Layout都有一个属性是collectionView,对应自己所属的collectionView。

 

@interface LTCollectionViewLayout : UICollectionViewLayout

   其次,在.m文件中,实现以下方法(按系统调用它们的顺序写的,当然四五六方法是我们主动调用的)

  (一)-(void)prepareLayout     

      在这个方法中一般进行一些数据的初始化,为下面的方法准备一些数据。记得一定要调用[super prepareLayout];

  (二)-(CGSize)collectionViewContentSize

      返回collectionView的可以滚动的区域大小。非必须重写方法,但笔者建议重写。

  (三)-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

      这个方法是最主要的,用来把所有的布局信息打包到一个数组里面,返回,告诉系统怎么布局。在该方法中我们主动调用下面三个方法获取想要的布局信息。

  (四)-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath

      返回indexPath处cell的布局信息,也就是说,cell的布局代码在这个方法里面写。

    (五)如果有各组有header或footer,or both,就实现

        -(UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath

      返回indexPath处的header或footer的布局信息

  (六)如果某一section有装饰,就实现

     -(UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath

      返回indexPath处的装饰的布局信息

其实,到这里,我们基本上已经知道怎么自定义layout了,下面给出一个非常简单的demo。

  先上图,git上的。

                                 

  

.h文件

@interface LTCollectionViewLayout : UICollectionViewLayout@end

 .m文件

#define decorationView @"decorationView"#import "LTCollectionViewLayout.h"#import "LTDecotationView.h"@interface LTCollectionViewLayout()@property(nonatomic,readonly)CGFloat cellCount;@property(nonatomic,readonly)CGPoint center;@property(nonatomic,readonly)CGFloat radius;@end@implementation LTCollectionViewLayout-(void)prepareLayout{    [super prepareLayout];    NSLog(@"prepareLayout");        CGSize size=self.collectionView.frame.size;    _cellCount=[[self collectionView] numberOfItemsInSection:0];//    圆心    _center=CGPointMake(size.height/3.5, size.width/1.5);//    半径    _radius=MIN(size.height, size.width)/2.5;    //    如果用到了装修,那么必须注册装饰,官方提供了以下两个方法    //    - (void)registerClass:(Class)viewClass forDecorationViewOfKind:(NSString *)elementKind;//    - (void)registerNib:(UINib *)nib forDecorationViewOfKind:(NSString *)elementKind;    //    注册装饰    [self registerClass:[LTDecotationView class] forDecorationViewOfKind:decorationView];    }/** *  此方法返回collectionView可以滚动的区域大小 * */-(CGSize)collectionViewContentSize{     NSLog(@"collectionViewContentSize");    return CGSizeMake(375, 2000);   }/** *  描述每个cell的布局信息,包括大小,位置等,布局信息封装到UICollectionViewLayoutAttributes对象中 */-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{    NSLog(@"layoutAttributesForItemAtIndexPath");    UICollectionViewLayoutAttributes *attributes=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];//    每个cell的大小    attributes.size=CGSizeMake(34.0 , 34.0);//    使用三角函数计算每个cell的中点位置    attributes.center=CGPointMake(_center.x + _radius*cosf(2*M_PI*indexPath.item/_cellCount), _center.y+_radius*sinf(2*M_PI*indexPath.item/_cellCount));    return attributes;}/** *  该方法返回值也是UICollectionViewLayoutAttributes对象,attributes对象中已经包含了SupplementaryView的布局信息,即header或footer,区分的方法是ofKind:后面的字符串 */-(UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{//    注意:初始化方法和cell、DecorationView不同    UICollectionViewLayoutAttributes *attributes=[UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath];        return attributes;}/**    使用了装饰,实现这个方法来描述DecorationView的布局 *  该方法返回值也是UICollectionViewLayoutAttributes对象,attributes对象中已经包含了装饰,使用它需要在自定义的layout的prepareLayout方法中注册,因为collectionView没有提供它的注册方法 * */-(UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{//    注意:初始化方法和cell、SupplementaryView不同    UICollectionViewLayoutAttributes *attributes=[UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:@"decorationView" withIndexPath:indexPath];    //    放在圆心处        attributes.center=self.center;//    尺寸        attributes.size=CGSizeMake(150,30);    return attributes;    }/** *  对一次显示某个区域的时候自动调用,对显示过的区域不会再调用该方法 */-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{         NSLog(@"layoutAttributesForElementsInRect,%@",NSStringFromCGRect(rect));    NSMutableArray *attributes=[NSMutableArray array];    //    1、添加cell的布局描述        for (int i =0; i

 

自定义的decoration,

.h

@interface LTDecotationView : UICollectionReusableView@end

 .m

#import "LTDecotationView.h"@implementation LTDecotationView-(instancetype)initWithFrame:(CGRect)frame{    if (self=[super initWithFrame:frame]) {                UILabel *label=[[UILabel alloc]initWithFrame:self.bounds];        label.text=@"DecotationView";        label.backgroundColor=[UIColor whiteColor];        [self addSubview:label];    }        return self;}@end

 

控制器.m文件

 
#define  collectionCell @"collectionCell"
#import "ViewController.h"
#import "LTCollectionViewLayout.h"@interface ViewController ()
@property(nonatomic,strong)UICollectionView *collectionView;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad];// 1、初始化collectionView LTCollectionViewLayout *myLayout=[[LTCollectionViewLayout alloc]init]; UICollectionView * myCollectionView=[[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 375, 667) collectionViewLayout:myLayout]; myCollectionView.backgroundColor=[UIColor purpleColor]; self.collectionView=myCollectionView; [self.view addSubview:myCollectionView];// 2、设置代理 self.collectionView.delegate=self; self.collectionView.dataSource=self; // 3、注册cell [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:collectionCell]; }-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ return 1;}-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return 20;}-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:collectionCell forIndexPath:indexPath]; cell.backgroundColor=[UIColor orangeColor]; return cell; }

 

转载于:https://www.cnblogs.com/panyuluoye/p/4923205.html

你可能感兴趣的文章
【转】百度地图api,根据多点注标坐标范围计算地图缩放级别zoom自适应地图
查看>>
用户调研(补)
查看>>
ExtJS之开篇:我来了
查看>>
☆1018
查看>>
oracle 去掉空格
查看>>
6.13心得
查看>>
Runtime类
查看>>
eclipse decompiler
查看>>
记一个搜索网盘资源的网站
查看>>
jdk1.7和jdk1.8的String的getByte方法的差异
查看>>
java父子进程通信
查看>>
Android ADB server didn't ACK * failed to start daemon * 简单有效的解决方案
查看>>
Olap学习笔记
查看>>
Codeforces Round #431 (Div. 1)
查看>>
如何进行数组去重
查看>>
将标题空格替换为 '_' , 并自动复制到剪切板上
查看>>
List Collections sort
查看>>
Mysql -- You can't specify target table 'address' for update in FROM clause
查看>>
使用局部标准差实现图像的局部对比度增强算法。
查看>>
2017-2018-1 20165313 《信息安全系统设计基础》第八周学习总结
查看>>