欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

自定义流水布局(UICollectionViewFlowLayout的基本使用)

程序员文章站 2022-06-23 15:40:30
最终显示的效果图 思路: 1、uicollection的基本设置,并且创建一个继承自uicollectionviewflowlayout的类。(不能是uicollectionviewlayout,...

最终显示的效果图

自定义流水布局(UICollectionViewFlowLayout的基本使用)

思路:

1、uicollection的基本设置,并且创建一个继承自uicollectionviewflowlayout的类。(不能是uicollectionviewlayout,否则全部都需要自定义)

2、在uicollectionviewflowlayout类中完成四步

  - 1)重写preparelayout方法进行基本的布局(cell在最左面的时候是在正中间),不能在init中布局,因为设置collectionview尺寸是在viewdidload中,而init在它之前调用,获得的collectionview的尺寸是空的

  - 2)重写shouldinvalidatelayoutforboundschange,当collectionview的显示范围发生改变的时候,让其内部重新布局(即让cell滚动起来)

  - 3)重写layoutattributesforelementsinrect方法,让cell在左右滑动的时候,尺寸放大或缩小

  - 4)重写targetcontentoffsetforproposedcontentoffset方法,让最接近中心的cell在停在正*。

 

代码如下:

viewcontorller中:

 1 #import "viewcontroller.h"
 2 #import "zwlinelayout.h"
 3 @interface viewcontroller () 
 4 @end
 5 @implementation viewcontroller
 6 static  nsstring *zwcellid = @"cell";
 7 - (void)viewdidload {
 8     [super viewdidload];
 9     //若为uicollectionviewlayout,itemsize和scrolldirection都需要自己写,下面的类继承自uicollectionviewlayout
10     zwlinelayout *layout = [[zwlinelayout alloc] init];
11     layout.itemsize = cgsizemake(160, 160);
12     cgrect rect = cgrectmake(0, 100, self.view.frame.size.width, self.view.frame.size.width * 0.6);
13     uicollectionview *collection = [[uicollectionview alloc] initwithframe:rect collectionviewlayout:layout];
14     collection.datasource = self;
15     collection.backgroundcolor = [uicolor greencolor];
16     [self.view addsubview:collection];
17     [collection registerclass:[uicollectionviewcell class] forcellwithreuseidentifier:zwcellid];
18 }
19 
20 #pragma mark - 数据源方法
21 - (nsinteger)collectionview:(uicollectionview *)collectionview numberofitemsinsection:(nsinteger)section
22 {
23     return 10;
24 }
25 - (uicollectionviewcell *)collectionview:(uicollectionview *)collectionview cellforitematindexpath:(nsindexpath *)indexpath
26 {
27     uicollectionviewcell *cell = [collectionview dequeuereusablecellwithreuseidentifier:zwcellid forindexpath:indexpath];
28     cell.backgroundcolor = [uicolor orangecolor];
29     return cell;
30 }

zwlinelayout.m中

 1 #import "zwlinelayout.h"
 2 
 3 @implementation zwlinelayout
 4 
 5 /**
 6  * 用来做布局的初始化操作(不建议在init方法中进行布局的初始化操作)
 7  */
 8 - (void)preparelayout
 9 {
10     [super preparelayout];
11     //水平滚动
12     self.scrolldirection = uicollectionviewscrolldirectionhorizontal;
13     
14     //
15     cgfloat margin = (self.collectionview.frame.size.width - self.itemsize.width) / 2;
16     self.collectionview.contentinset = uiedgeinsetsmake(0, margin, 0, margin);
17 }
18 
19 /**
20  * 当collectionview的显示范围发生改变的时候,是否需要重新刷新布局
21  * 一旦重新刷新布局,就会重新调用下面的方法:
22  * 1.preparelayout
23  * 2.layoutattributesforelementsinrect:方法
24  */
25 - (bool)shouldinvalidatelayoutforboundschange:(cgrect)newbounds
26 {
27     return yes;
28 }
29 
30 
31 /**
32  * 这个方法的返回值是一个数组(数组里面存放着rect范围内所有元素的布局属性)
33  * 这个方法的返回值决定了rect范围内所有元素的排布(frame)
34  */
35 //需要在viewcontroller中使用上zwlinelayout这个类后才能重写这个方法!!
36 - (nsarray *)layoutattributesforelementsinrect:(cgrect)rect
37 {
38     //让父类布局好样式
39     nsarray *arr = [super layoutattributesforelementsinrect:rect];
40     //计算出collectionview的中心的位置
41     cgfloat ceterx = self.collectionview.contentoffset.x + self.collectionview.frame.size.width * 0.5;
42     /**
43      * 1.一个cell对应一个uicollectionviewlayoutattributes对象
44      * 2.uicollectionviewlayoutattributes对象决定了cell的frame
45      */
46     for (uicollectionviewlayoutattributes *attributes in arr) {
47         //cell的中心点距离collectionview的中心点的距离,注意abs()表示绝对值
48         cgfloat delta = abs(attributes.center.x - ceterx);
49         //设置缩放比例
50         cgfloat scale = 1.1 - delta / self.collectionview.frame.size.width;
51         //设置cell滚动时候缩放的比例
52         attributes.transform = cgaffinetransformmakescale(scale, scale);
53     }
54     
55     return arr;
56 }
57 
58 /**
59  * 这个方法的返回值,就决定了collectionview停止滚动时的偏移量
60  */
61 - (cgpoint)targetcontentoffsetforproposedcontentoffset:(cgpoint)proposedcontentoffset withscrollingvelocity:(cgpoint)velocity
62 {
63     // 计算出最终显示的矩形框
64     cgrect rect;
65     rect.origin.y = 0;
66     rect.origin.x = proposedcontentoffset.x;
67     rect.size = self.collectionview.frame.size;
68     
69     //获得super已经计算好的布局的属性
70     nsarray *arr = [super layoutattributesforelementsinrect:rect];
71     
72     //计算collectionview最中心点的x值
73     cgfloat centerx = proposedcontentoffset.x + self.collectionview.frame.size.width * 0.5;
74     
75     cgfloat mindelta = maxfloat;
76     for (uicollectionviewlayoutattributes *attrs in arr) {
77         if (abs(mindelta) > abs(attrs.center.x - centerx)) {
78             mindelta = attrs.center.x - centerx;
79         }
80     }
81     proposedcontentoffset.x += mindelta;
82     return proposedcontentoffset;
83 }
84 @end