ios uicollectionview实现横向滚动
程序员文章站
2023-11-22 14:17:40
现在使用卡片效果的app很多,之前公司让实现一种卡片效果,就写了一篇关于实现卡片的文章。文章最后附有demo实现上我选择了使用uicollectionview ;用uicollectionviewfl...
现在使用卡片效果的app很多,之前公司让实现一种卡片效果,就写了一篇关于实现卡片的文章。文章最后附有demo
实现上我选择了使用uicollectionview ;用uicollectionviewflowlayout来定制样式;下面看看具体实现
效果
实现上我选择了使用uicollectionview ;用uicollectionviewflowlayout来定制样式;下面看看具体实现
具体实现
1、viviewcontroller.m 代码实现
#import "viewcontroller.h" #import "collmodel.h" #define screen_width [uiscreen mainscreen].bounds.size.width #define screen_height [uiscreen mainscreen].bounds.size.height #define screen_rate ([uiscreen mainscreen].bounds.size.width/375.0) #import "imagecell.h" #import "lhhorizontalpageflowlayout.h" static nsstring * const imagec = @"imagecell"; static nsstring * const moreimagec = @"imagecell"; static const nsinteger kitemcountperrow = 5; //每行显示5个 static const nsinteger krowcount = 3; //每页显示行数 static float imageheight = 80;//cell 高度 @interface viewcontroller ()<uicollectionviewdelegate,uicollectionviewdatasource> @property (nonatomic, strong) uicollectionview * collectionview; @property (nonatomic, strong) nsmutablearray * modelarray; @property (nonatomic, strong) uicollectionview * morecollectionview; @end @implementation viewcontroller - (void)viewdidload { [super viewdidload]; nsarray *apparray = [[self getdict] objectforkey:@"dictinfo"]; for (int i = 0; i < apparray.count; i++) { nsdictionary * appdic = apparray[i]; collmodel * model = [[collmodel alloc]init]; model.title = [appdic objectforkey:@"title"]; model.url = [appdic objectforkey:@"url"]; [self.modelarray addobject:model]; } [self createcollectionview]; [self createrightcollectionview]; } - (nsdictionary *)getdict { nsstring * string = @"{\"dictinfo\":[{\"title\":\"你好啊\",\"url\":\"1.jpeg\"},{\"title\":\"你好啊\",\"url\":\"2.jpeg\"},{\"title\":\"你好啊\",\"url\":\"3.jpeg\"},{\"title\":\"你好啊\",\"url\":\"4.jpeg\"},{\"title\":\"你好啊\",\"url\":\"5.jpeg\"},{\"title\":\"你好啊\",\"url\":\"6.jpeg\"},{\"title\":\"是很好\",\"url\":\"7.jpeg\"},{\"title\":\"你好啊\",\"url\":\"1.jpeg\"},{\"title\":\"你好啊\",\"url\":\"2.jpeg\"},{\"title\":\"你好啊\",\"url\":\"3.jpeg\"},{\"title\":\"你好啊\",\"url\":\"4.jpeg\"},{\"title\":\"你好啊\",\"url\":\"5.jpeg\"},{\"title\":\"你好啊\",\"url\":\"6.jpeg\"},{\"title\":\"是很好\",\"url\":\"7.jpeg\"},{\"title\":\"你好啊\",\"url\":\"1.jpeg\"},{\"title\":\"你好啊\",\"url\":\"2.jpeg\"},{\"title\":\"你好啊\",\"url\":\"3.jpeg\"},{\"title\":\"你好啊\",\"url\":\"4.jpeg\"},{\"title\":\"你好啊\",\"url\":\"5.jpeg\"},{\"title\":\"你好啊\",\"url\":\"6.jpeg\"},{\"title\":\"是很好\",\"url\":\"7.jpeg\"}]}"; nsdictionary *infodic = [self dictionarywithjsonstring:string]; return infodic; } -(nsdictionary *)dictionarywithjsonstring:(nsstring *)jsonstring { if (jsonstring == nil) { return nil; } nsdata *jsondata = [jsonstring datausingencoding:nsutf8stringencoding]; nserror *err; nsdictionary *dic = [nsjsonserialization jsonobjectwithdata:jsondata options:nsjsonreadingmutablecontainers error:&err]; if(err) { nslog(@"json解析失败:%@",err); return nil; } return dic; } - (nsmutablearray *)modelarray { if (!_modelarray) { _modelarray = [nsmutablearray array]; } return _modelarray; } - (void)createcollectionview{ uicollectionviewflowlayout * layout = [[uicollectionviewflowlayout alloc]init]; layout.scrolldirection = uicollectionviewscrolldirectionhorizontal; layout.minimumlinespacing = 0; layout.minimuminteritemspacing = 0; _collectionview = [[uicollectionview alloc] initwithframe:cgrectmake(0, 100, [uiscreen mainscreen].bounds.size.width, imageheight * screen_rate) collectionviewlayout:layout]; _collectionview.tag = 11; _collectionview.backgroundcolor = [uicolor colorwithred:186 / 255.0 green:186 / 255.0 blue:186 / 255.0 alpha:0.9]; _collectionview.datasource = self; _collectionview.delegate = self; _collectionview.bounces = no; _collectionview.alwaysbouncehorizontal = yes; _collectionview.alwaysbouncevertical = no; _collectionview.showshorizontalscrollindicator = no; _collectionview.showsverticalscrollindicator = no; [self.view addsubview:_collectionview]; [_collectionview registerclass:[imagecell class] forcellwithreuseidentifier:imagec]; } - (void)createrightcollectionview{ lhhorizontalpageflowlayout * layout = [[lhhorizontalpageflowlayout alloc] initwithrowcount:krowcount itemcountperrow:kitemcountperrow]; [layout setcolumnspacing:0 rowspacing:0 edgeinsets:uiedgeinsetsmake(0, 0, 0, 0)]; layout.scrolldirection = uicollectionviewscrolldirectionhorizontal; // uicollectionviewflowlayout *layout = [[uicollectionviewflowlayout alloc]init]; // layout.scrolldirection = uicollectionviewscrolldirectionhorizontal; layout.minimumlinespacing = 0; layout.minimuminteritemspacing = 0; _morecollectionview = [[uicollectionview alloc] initwithframe:cgrectmake(0, 300, [uiscreen mainscreen].bounds.size.width, imageheight * screen_rate * krowcount) collectionviewlayout:layout]; _morecollectionview.backgroundcolor = [uicolor clearcolor]; _morecollectionview.tag = 22; _morecollectionview.datasource = self; _morecollectionview.delegate = self; _morecollectionview.bounces = no; _morecollectionview.alwaysbouncehorizontal = yes; _morecollectionview.alwaysbouncevertical = no; _morecollectionview.backgroundcolor = [uicolor colorwithred:186 / 255.0 green:186 / 255.0 blue:186 / 255.0 alpha:0.9]; _morecollectionview.showshorizontalscrollindicator = no; _morecollectionview.showsverticalscrollindicator = no; [self.view addsubview:_morecollectionview]; [_morecollectionview registerclass:[imagecell class] forcellwithreuseidentifier:moreimagec]; } - (nsinteger)collectionview:(uicollectionview *)collectionview numberofitemsinsection:(nsinteger)section{ return self.modelarray.count; } - (uicollectionviewcell *)collectionview:(uicollectionview *)collectionview cellforitematindexpath:(nsindexpath *)indexpath { collmodel * model = self.modelarray[indexpath.row]; imagecell * cell = [collectionview dequeuereusablecellwithreuseidentifier:imagec forindexpath:indexpath]; cell.itemmodel = model; return cell; } // 返回每个item的大小 - (cgsize)collectionview:(uicollectionview *)collectionview layout:(uicollectionviewlayout *)collectionviewlayout sizeforitematindexpath:(nsindexpath *)indexpath { cgfloat cwidth = imageheight * screen_rate; cgfloat cheight = imageheight * screen_rate; return cgsizemake(cwidth, cheight); } #pragma mark - uicollectionviewdelegate点击事件 - (void)collectionview:(uicollectionview *)collectionview didselectitematindexpath:(nsindexpath *)indexpath{ collmodel * model = self.modelarray[indexpath.row]; nslog(@"self.appmodelarray----%@",model.title); } - (void)didreceivememorywarning { [super didreceivememorywarning]; // dispose of any resources that can be recreated. } @end
2、自定义uicollectionviewflowlayout
lhhorizontalpageflowlayout.h 实现
#import <uikit/uikit.h> @interface lhhorizontalpageflowlayout : uicollectionviewflowlayout /** 列间距 */ @property (nonatomic, assign) cgfloat columnspacing; /** 行间距 */ @property (nonatomic, assign) cgfloat rowspacing; /** collectionview的内边距 */ @property (nonatomic, assign) uiedgeinsets edgeinsets; /** 多少行 */ @property (nonatomic, assign) nsinteger rowcount; /** 每行展示多少个item */ @property (nonatomic, assign) nsinteger itemcountperrow; //固定宽度 @property (nonatomic, assign) cgfloat itemwidth; //设置完这个,就会自动计算列间距 //固定高度 @property (nonatomic, assign) cgfloat itemhight;//设置完这个,就会自动计算行间距 /** 所有item的属性数组 */ @property (nonatomic, strong) nsmutablearray *attributesarraym; /** 设置行列间距及collectionview的内边距 */ - (void)setcolumnspacing:(cgfloat)columnspacing rowspacing:(cgfloat)rowspacing edgeinsets:(uiedgeinsets)edgeinsets; /** 设置多少行及每行展示的item个数 */ - (void)setrowcount:(nsinteger)rowcount itemcountperrow:(nsinteger)itemcountperrow; #pragma mark - 构造方法 /** 设置多少行及每行展示的item个数 */ + (instancetype)horizontalpageflowlayoutwithrowcount:(nsinteger)rowcount itemcountperrow:(nsinteger)itemcountperrow; /** 设置多少行及每行展示的item个数 */ - (instancetype)initwithrowcount:(nsinteger)rowcount itemcountperrow:(nsinteger)itemcountperrow; @end
lhhorizontalpageflowlayout.m 实现
#import "lhhorizontalpageflowlayout.h" @implementation lhhorizontalpageflowlayout #pragma mark - public - (void)setcolumnspacing:(cgfloat)columnspacing rowspacing:(cgfloat)rowspacing edgeinsets:(uiedgeinsets)edgeinsets { self.columnspacing = columnspacing; self.rowspacing = rowspacing; self.edgeinsets = edgeinsets; } - (void)setrowcount:(nsinteger)rowcount itemcountperrow:(nsinteger)itemcountperrow { self.rowcount = rowcount; self.itemcountperrow = itemcountperrow; } #pragma mark - 构造方法 + (instancetype)horizontalpageflowlayoutwithrowcount:(nsinteger)rowcount itemcountperrow:(nsinteger)itemcountperrow { return [[self alloc] initwithrowcount:rowcount itemcountperrow:itemcountperrow]; } - (instancetype)initwithrowcount:(nsinteger)rowcount itemcountperrow:(nsinteger)itemcountperrow { self = [super init]; if (self) { self.rowcount = rowcount; self.itemcountperrow = itemcountperrow; } return self; } #pragma mark - 重写父类方法 - (instancetype)init { self = [super init]; if (self) { [self setcolumnspacing:0 rowspacing:0 edgeinsets:uiedgeinsetszero]; } return self; } /** 布局前做一些准备工作 */ - (void)preparelayout { [super preparelayout]; if (self.attributesarraym && self.attributesarraym.count > 0) { [self.attributesarraym removeallobjects]; } // 从collectionview中获取到有多少个item nsinteger itemtotalcount = [self.collectionview numberofitemsinsection:0]; // 遍历出item的attributes,把它添加到管理它的属性数组中去 for (int i = 0; i < itemtotalcount; i++) { nsindexpath *indexpath = [nsindexpath indexpathforitem:i insection:0]; uicollectionviewlayoutattributes *attributes = [self layoutattributesforitematindexpath:indexpath]; [self.attributesarraym addobject:attributes]; } } /** 计算collectionview的滚动范围 */ - (cgsize)collectionviewcontentsize { // 计算出item的宽度 cgfloat itemwidth = (self.collectionview.frame.size.width - self.edgeinsets.left - self.itemcountperrow * self.columnspacing) / self.itemcountperrow; // 从collectionview中获取到有多少个item nsinteger itemtotalcount = [self.collectionview numberofitemsinsection:0]; // 理论上每页展示的item数目 nsinteger itemcount = self.rowcount * self.itemcountperrow; // 余数(用于确定最后一页展示的item个数) nsinteger remainder = itemtotalcount % itemcount; // 除数(用于判断页数) nsinteger pagenumber = itemtotalcount / itemcount; // 总个数小于self.rowcount * self.itemcountperrow if (itemtotalcount <= itemcount) { pagenumber = 1; }else { if (remainder == 0) { pagenumber = pagenumber; }else { // 余数不为0,除数加1 pagenumber = pagenumber + 1; } } cgfloat width = 0; // 考虑特殊情况(当item的总个数不是self.rowcount * self.itemcountperrow的整数倍,并且余数小于每行展示的个数的时候) if (pagenumber > 1 && remainder != 0 && remainder < self.itemcountperrow) { width = self.edgeinsets.left + (pagenumber - 1) * self.itemcountperrow * (itemwidth + self.columnspacing) + remainder * itemwidth + (remainder - 1)*self.columnspacing + self.edgeinsets.right; }else { width = self.edgeinsets.left + pagenumber * self.itemcountperrow * (itemwidth + self.columnspacing) - self.columnspacing + self.edgeinsets.right; } // 只支持水平方向上的滚动 return cgsizemake(width, 150); } /** 设置每个item的属性(主要是frame) */ - (uicollectionviewlayoutattributes *)layoutattributesforitematindexpath:(nsindexpath *)indexpath { // item的宽高由行列间距和collectionview的内边距决定 cgfloat itemwidth = (self.collectionview.frame.size.width) / self.itemcountperrow; cgfloat itemheight = (self.collectionview.frame.size.height) / self.rowcount; nsinteger item = indexpath.item; // 当前item所在的页 nsinteger pagenumber = item / (self.rowcount * self.itemcountperrow); nsinteger x = item % self.itemcountperrow + pagenumber * self.itemcountperrow; nsinteger y = item / self.itemcountperrow - pagenumber * self.rowcount; // 计算出item的坐标 cgfloat itemx = itemwidth * x; cgfloat itemy = itemheight * y; uicollectionviewlayoutattributes *attributes = [super layoutattributesforitematindexpath:indexpath]; // 每个item的frame attributes.frame = cgrectmake(itemx, itemy, itemwidth, itemheight); return attributes; } /** 返回collectionview视图中所有视图的属性数组 */ - (nsarray<uicollectionviewlayoutattributes *> *)layoutattributesforelementsinrect:(cgrect)rect { return self.attributesarraym; } #pragma mark - lazy - (nsmutablearray *)attributesarraym { if (!_attributesarraym) { _attributesarraym = [nsmutablearray array]; } return _attributesarraym; } @end
4、自定义cell 和model
model
#import <foundation/foundation.h> @interface collmodel : nsobject @property (nonatomic,strong)nsstring *imgurl; @property (nonatomic,strong)nsstring *title; @property (nonatomic,strong)nsstring *url; @end
cell 自定义
#import "imagecell.h" // 屏幕比例 #define screen_rate ([uiscreen mainscreen].bounds.size.width/375.0) @interface imagecell() @property (nonatomic, strong) uiimageview *itemicon; @end @implementation imagecell @synthesize itemmodel = _itemmodel; - (instancetype)initwithframe:(cgrect)frame{ if (self = [super initwithframe:frame]) { self.contentview.backgroundcolor = [uicolor clearcolor]; [self initview]; } return self; } - (void)initview{ _itemicon = [[uiimageview alloc] init]; [self.contentview addsubview:_itemicon]; _itemicon.backgroundcolor = [uicolor clearcolor]; cgfloat iconwidth = 80 * screen_rate; _itemicon.frame = cgrectmake(0, 0, iconwidth, iconwidth); _itemicon.center = self.contentview.center; } - (collmodel *)itemmodel{ return _itemmodel; } - (void)setitemmodel:(collmodel *)itemmodel { if (!itemmodel) { return; } _itemmodel = itemmodel; [self setcellwithmodel:_itemmodel]; } - (void)setcellwithmodel:(collmodel *)itemmodel{ [[nsoperationqueue mainqueue] addoperationwithblock:^{ _itemicon.image = [uiimage imagenamed:itemmodel.url]; }]; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: PS制作逼真的水面倒影效果图
下一篇: Linux 中 MySQL 授权远程连接