美文网首页iOS小筑UI进价iOS 开发 学习
横向分页滚动的UICollectionView,cell左右排版

横向分页滚动的UICollectionView,cell左右排版

作者: wwwbbat | 来源:发表于2016-04-26 16:15 被阅读19456次

已更新Demo(2017-8-8):
https://pan.baidu.com/s/1bDXrYI
不放github了

下面这种需求应该是会经常遇到的:
需求:固定高度一个区域,里面左右分页显示很多个图标,在每一页中的图标先从左往右排,排满后再从上往下排。这一页排满后排下一页。
图中这样的:上面cell的顺序我已经标出来了。


p1.png

像这样的需求,第一反应是用UICollectionView来写,用UICollectionViewFlowLayout,然后设置为横向的。但是,采用这种方式来写,出来的效果就会是这样的:


p2.png

那么还可以怎么实现?可以用大的cell包5个小图标在里面。这样实现按说没问题,但是如果单个图标这里复杂一点,就需要调很久了,而且如果要根据屏幕尺寸来定每行显示的图标个数也很麻烦。

下面是我的实现:

子类化 UICollectionViewFlowLayout

DDCollectionViewHorizontalLayout.h
@interface DDCollectionViewHorizontalLayout : UICollectionViewFlowLayout
// 一行中 cell的个数
@property (nonatomic) NSUInteger itemCountPerRow;
// 一页显示多少行
@property (nonatomic) NSUInteger rowCount;
@end

DDCollectionViewHorizontalLayout.m
@interface DDCollectionViewHorizontalLayout ()
@property (strong, nonatomic) NSMutableArray *allAttributes;
@end
- (void)prepareLayout
{
    [super prepareLayout];

    self.allAttributes = [NSMutableArray array];

    NSUInteger count = [self.collectionView numberOfItemsInSection:0];
    for (NSUInteger i = 0; i<count; i++) {
       NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
        [self.allAttributes addObject:attributes];
    }
}

- (CGSize)collectionViewContentSize
{
    return [super collectionViewContentSize];
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger item = indexPath.item;
    NSUInteger x;
    NSUInteger y;
    [self targetPositionWithItem:item resultX:&x resultY:&y];
    NSUInteger item2 = [self originItemAtX:x y:y];
    NSIndexPath *theNewIndexPath = [NSIndexPath indexPathForItem:item2 inSection:indexPath.section];

    UICollectionViewLayoutAttributes *theNewAttr = [super layoutAttributesForItemAtIndexPath:theNewIndexPath];
    theNewAttr.indexPath = indexPath;
    return theNewAttr;
}

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];

    NSMutableArray *tmp = [NSMutableArray array];

    for (UICollectionViewLayoutAttributes *attr in attributes) {
        for (UICollectionViewLayoutAttributes *attr2 in self.allAttributes) {
            if (attr.indexPath.item == attr2.indexPath.item) {
                [tmp addObject:attr2];
                break;
            }
        }
    }
    return tmp;
}

// 根据 item 计算目标item的位置
// x 横向偏移  y 竖向偏移
- (void)targetPositionWithItem:(NSUInteger)item
                       resultX:(NSUInteger *)x
                       resultY:(NSUInteger *)y
{
    NSUInteger page = item/(self.itemCountPerRow*self.rowCount);

    NSUInteger theX = item % self.itemCountPerRow + page * self.itemCountPerRow;
    NSUInteger theY = item / self.itemCountPerRow - page * self.rowCount;
    if (x != NULL) {
        *x = theX;
    }
    if (y != NULL) {
        *y = theY;
    }
}

// 根据偏移量计算item
- (NSUInteger)originItemAtX:(NSUInteger)x
                          y:(NSUInteger)y
{
    NSUInteger item = x * self.rowCount + y;
    return item;
}

@end

需要注意的

我这个简单的实现只支持1个section,而且section的items个数必须是 itemCountPerRow * rowCount 的整数倍。这里需要在UICollectionView的代理里面做好数组越界检查,防止数组越界造成崩溃。
完整的实现以后再说吧,现在这样已经满足需求了。

相关文章

网友评论

  • 啊哈哈哈哈哈群:多个section的时候 如何指定某一个section横向滑动呢
  • 幸福的鱼:多谢分享
  • 黑鱼仔:为什么设置不了headerview呢
  • 3ef31b313c61:横向整屏滚动 怎么加定时器 无限循环
  • 83b7dcaa63cf:加上下面的代码可以在超过一页,但是剩下的item不够一页的时候让剩下的item占满一页
    - (CGSize)collectionViewContentSize
    {
    NSUInteger count = [self.collectionView numberOfItemsInSection:0];
    NSUInteger perPage = self.rowCount * self.itemCountPerRow;
    NSUInteger time = count / perPage;
    CGSize size = self.collectionView.frame.size;
    size.width = size.width * (time + 1);
    return size;
    }

    其实就是设置ContentSize
  • elite_kai:楼主你好,借用一下宝地哈哈
    http://www.jianshu.com/p/35349e50b637
  • 薐驚:nice
  • wustzhy:楼主, 我设置的 2行 3列, cellForItem方法, 每次都跳过item2,第2个cell就这么凭空消失了.然后,item 2的位置就是空白的
    天然酱油:我设置了2行4列 在只有6个的时候第四个就不见了,其他的都没问题,有大神知道吗?
    明似水:item 2凭空消失怎么处理?
  • 摇曳的芦苇:为什么刷新时数据有的不显示呢
  • 1e68a36b8adc:放一下 demo 呗 共同学习
  • Onein:占用宝地 哈哈 。横向滚动的日历:http://onein.cf/
  • ios肖:不错不错,感谢技术分享
  • 癫佬:楼主,我设置三行两列,当我添加到第三个Cell时,第二个cell会消失等再继续增加时才会再次出现,这是什么原因
    wustzhy:我也出现这个情况, 兄台你搞定没,很难搞啊
  • Onein:免费 提供 Demo 地址 : https://github.com/GouWeiBaCao/CollectionViewDemoWithHorziDispaly
    Onein:@avaj之简书 我是直接在项目中写的,然后从项目里copy出来才写的那个demo,应该没问题的吧。。。
    抄无止境:@Onein 我下载你的demo,但是提取出来后,在其他项目中是不显示的,也不知道什么原因.你的在任何地方这种写法都可以显示吗?
    Onein:@Onein 我自己又写了个横向滚动的日历 ,欢迎吐槽:http://onein.cf/
  • 46e1f2b6bed8:求demo 181008352@qq.com
  • 取个名字好难11:求demo 2449974535@qq.com
  • 迷恋代码:492262370@qq.com
  • 迷恋代码:Demo可以发给我看看不
  • 806f285782ef:我的 UICollectionViewLayoutAttributes *theNewAttr 对象是nil, NSUInteger item = indexPath.item;也是nil 导致我添加[self.allAttributes addObject:attributes]; 是空 报错 crash 是什么情况?
    b3565c45d116:@iaffan 继承于UICollectionViewFlowLayout而不是UICollectionViewLayout
    b3565c45d116:@DL丨金成武  遇到同样的问题
  • 3d021e52b4ba:求demo
  • 05e8265e473a:不知道有没有demo啊,这个干货真的很需要。
  • gyq琪琪:大神, 来个Demo吧
  • ba7fa2253359:有demo吗?大神..就这个横排横滑的..我现在完成了不够就补齐的需求,,但是还是按列排列成了..503459002@qq.com,大神赐教
  • drop凯:不是 itemCountPerRow * rowCount 的整数倍 的楼主 搞了没
    Alan龙马:@05e8265e473a 根据个数隐藏掉就好啦
    05e8265e473a:但是服务器返回的个数是不一定的,怎么判断呢
    wwwbbat:@drop凯 不是整数倍 就凑成整数倍就好了。 :stuck_out_tongue_winking_eye:

本文标题:横向分页滚动的UICollectionView,cell左右排版

本文链接:https://www.haomeiwen.com/subject/zugqrttx.html