自定义流水布局(UICollectionViewFlowLayout的基本使用)
程序员文章站
2022-03-09 22:36:51
最终显示的效果图
思路:
1、uicollection的基本设置,并且创建一个继承自uicollectionviewflowlayout的类。(不能是uicollectionviewlayout,...
最终显示的效果图
思路:
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
推荐阅读
-
UICollectionView的水平流水布局自定义layout
-
Android 深入探究自定义view之流式布局FlowLayout的使用
-
解决使用Notification自定义布局时出现android.app.RemoteServiceException Bad notification posted的问题
-
Android Tablayout 自定义Tab布局的使用案例
-
Android基础-四种基本布局和自定义控件的步骤
-
移动应用开发——FrameLayout(帧布局)的基本使用
-
自定义流水布局(UICollectionViewFlowLayout的基本使用)
-
自定义注解的基本使用
-
UICollectionView的水平流水布局自定义layout
-
使用有趣的自定义标记布局页面_经验交流