ios uicollectionview实现横向滚动

现在使用卡片效果的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下载

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

时间: 2020-03-22

iOS Swift UICollectionView横向分页滚动,cell左右排版问题详解

情况 Swift对于一门新的iOS编程语言,他的崛起是必然的,我们这群老程序员们学习新的技能也是必然的,不接受新技能将被这大群体无情的淘汰. 最近因为工作的需求,在做表情键盘时遇到一个问题,我用UICollectionView来布局表情,使用横向分页滚动,但在最后一页出现了如图所示的情况 情况分析图 是的,现在的item分布就是这个鬼样子 现在想要做的,就是将现在这个鬼样子变成另外一种样子,如图 那怎么办?只好重新布局item了 解决方案 我是自定了一个Layout(LXFChatEmotion

iOS使用UICollectionView实现横向滚动照片效果

本文实例为大家分享了iOS使用UICollectionView实现横向滚动展示照片的具体代码,供大家参考,具体内容如下 这是Demo链接 效果图 思路 1. 界面搭建 界面的搭建十分简单,采用UICollectionView和自定义cell进行搭建即可. // ViewController.m // 下面使用到的宏和全局变量 #define ScreenW [UIScreen mainScreen].bounds.size.width #define ScreenH [UIScreen main

ios基于UICollectionView实现横向瀑布流

在网上找了许久,一直没有发现有提供横向瀑布流效果的.在项目中用到了我就在垂直瀑布流的基础上,进行了修改,做出了横向瀑布流的效果.同时也对一些UICollectionView的属性进行简单的注释,方便以后查阅. 1.首先要写一个继承与NSObject的布局类,记录每一行(列)目前的宽度(高度).再添加一个新的cell的时候进行判断比较,添加到最短的那一行或一列上. 2.横向的布局类入下,垂直的话就是讲对应的X Y轴数据进行调整即可. WaterfallFlowLayout为布局类,继承与NSObj

IOS使用UICollectionView实现无限轮播效果

一.案例演示 本案例Demo演示的是一个首页轮播的案例,支持手动轮播和自动轮播.知识点主要集中在UICollectionView和NSTimer的使用. 二.知识储备 2.1.UICollectionView横向布局 只需要设置UICollectionViewFlowLayout的scrollDirection为UICollectionViewScrollDirectionHorizontal即可. 2.2.NSTimer的基本使用 NSTimer的初始化: 复制代码 代码如下: + (NSTi

iOS使用UICollectionView实现列表头部拉伸效果

本文实例为大家分享了iOS实现列表下拉放大效果展示的具体代码,供大家参考,具体内容如下 先看效果图 突然发现没有做出来之前都觉得蛮难的,做出来之后就觉得So Easy 大家都有这样的感触吧 做这个就重写 UICollectionViewFlowLayout 的几个方法就可以 OC版本 创建一个类 CustomCollectionViewFlowLayout 继承 UICollectionViewFlowLayout // // CustomCollectionViewFlowLayout.m /

iOS UICollectionView实现横向滑动

本文实例为大家分享了iOS UICollectionView实现横向滑动的具体代码,供大家参考,具体内容如下 UICollectionView的横向滚动,目前我使用在了显示输入框的输入历史上: // // SCVisitorInputAccessoryView.m // 访客通行录入页面--访客姓名输入历史的InputAccessory #import "SCInputAccessoryView.h" #import "SCInputAccessoryCell.h"

JS实现图片横向滚动效果示例代码

复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv=&qu

jQuery文字横向滚动效果的实现代码

很多网站都有公告,并且都喜欢用横向滚动的方式来展现.最近自己用jQuery也写了文字横向滚动,实现了自定义滚动速度,鼠标经过时暂停的功能. HTML代码如下: <div id="s" style="width:100px; position:relative; white-space:nowrap; overflow:hidden; height:20px;"> <div id="noticeList" style="

Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条

本博主在一次个人移动端项目中,遇到这么一个需求:希望自己的项目中,头部导航条的效果可以像今日头条那样,横向滚动! 对于这样的效果,在各大移动端项目中几乎是随处可见,为什么呢? 我们都知道,对于移动端也就是手机上,我们页面的宽度并不像PC端那样大,可以显示很长的导航项,但对于我们移动端来说,由于功能的拓展,或者业务的细分,往往导航项也会随之增多,一旦超过移动端在一行的页面显示宽度,那便会出现导航项换行的现象,虽说也有这样布局,但一旦导航项增多到一定程度的时候,我们的页面(首页)将均被导航项霸占,这

iOS模拟中奖名单循环滚动效果

本文实例为大家分享了iOS模拟中奖名单循环滚动效果的具体代码,供大家参考,具体内容如下 1.动态效果图: 2.思路: (1)控件:一个父View,依次添加两个tableVew,使其上下紧挨着,高度均等于所有cell的总高度,且加载相同的的数据,父视图的clipsToBounds属性一定要设置为true (2)滚动:使用计时器,调整时间及滚动大小,使展示平滑 (3)循环算法:当A列表滚动出界面时,就把它添加在B列表的下面,B列表滚动出界面时,就把它添加在A列表的下面,形成循环效果 3.Swift版