美文网首页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/
      • xiaomaolv:求demo 181008352@qq.com
      • 取个名字好难11:求demo 2449974535@qq.com
      • 迷恋代码:492262370@qq.com
      • 迷恋代码:Demo可以发给我看看不
      • DL丨金成武:我的 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吧
      • 白云觅雪014:有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