当前位置: 萬仟网 > 移动技术>移动开发>IOS > ios uicollectionview实现横向滚动

ios uicollectionview实现横向滚动

2020年06月23日  | 萬仟网移动技术  | 我要评论

现在使用卡片效果的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];
 }];
}

下载:ios uicollectionview横向滚动

github下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持萬仟网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
Copyright © 2017-2020  萬仟网 保留所有权利. 粤ICP备17035492号-1
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com