UICollectionView“流向”

Posted

技术标签:

【中文标题】UICollectionView“流向”【英文标题】:UICollectionView "flow direction" 【发布时间】:2018-11-01 16:31:09 【问题描述】:

UICollectionView 的典型流程是“移动,然后向下”

我很好奇是否有办法颠倒“流”的顺序,即“先向下”(最大行数,然后越过。)类似于这样:

【问题讨论】:

将流式布局的滚动方向改为水平。 @rmaddy 鉴于第二张图,请求似乎是保持滚动方向垂直。 【参考方案1】:

我很好奇是否有办法颠倒“流”的顺序,即“先向下”(最大行数,然后越过。)

没有办法让UICollectionFlowLayout 以列优先顺序排列单元格 - 它首先“流动”单元格,然后向下。如果您考虑一下,这是有道理的——UICollectionFlowLayout 如何知道在开始第二列之前要在第一列中放置多少个单元格?事实上,它只是在移动到下一行之前放置尽可能多的行。但是由于您希望滚动方向保持垂直,因此没有任何理由停止将单元格添加到第一列。

但是UICollectionView 会很乐意将单元格放置在您喜欢的任何位置——您只需创建自己的自定义布局对象来告诉它放置它们的位置。这并不像听起来那么令人生畏...在网格上布置单元格不是火箭科学,而且您的集合布局对象不必像UICollectionFlowLayout 那样健壮——它只是必须满足您的特定需求。

【讨论】:

感谢您的回复。 在不实现自己的流布局的情况下,按列主要顺序排列给定数据会更容易。 @RatulSharker 列数通常不是恒定的。例如,设备可能会旋转,或者用户可能会在两个应用之间拆分屏幕。 是的,列数不是恒定的,但可以很容易地计算出来。就要求创建两行而言,只需将元素总数除以二即可得出列数。 @RatulSharker 也许那应该是一个答案而不是评论。【参考方案2】:

感谢@Caleb 启发了我。我尝试了以下设置

class ViewController: UIViewController 
    let items = ["A", "B", "C", "D", "E"]

    // other unnecessary stuff for this demonstration


extension ViewController: UICollectionViewDataSource 
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        if section == 0 
            return ((items.count + 1) / 2) // just ceiling, after dividing by 2
         else  if section == 1 
            return items.count - ((items.count + 1) / 2) // calculating the remainder item
         else 
            return 0
        
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)

        var text = "";
        if indexPath.section == 0 
            // take the even part
            text = items[indexPath.row * 2]
         else 
            // take the odd part
            text = items[(indexPath.row * 2) + 1]
        

        (cell.subviews[0].subviews[0] as? UILabel)?.text = text

        return cell
    

    func numberOfSections(in collectionView: UICollectionView) -> Int 
        return 2
    

我将滚动方向设置为vertical,输出看起来像这样。它适用于奇数项和偶数项。

显然这不是 OP 正在寻找的。在这里,我使用了两个不同的部分,但 OP 想要在一个部分中制作锯齿形图案。正如@Caleb 整理的那样,这当然不可能,如果不填充宽度,我们就不能在垂直方向下降。

【讨论】:

如果您有更多数据,您当然可以通过重新排列数据来伪造列主要顺序。在我看来,OP 并没有特别要求两行......他/她只是想通过向下推进列而不是跨行来填充单元格。毫无疑问,这种方法可以做到这一点。我认为这是一个快速而肮脏的解决方案——快速是因为它比编写布局类要少得多;肮脏,因为它会在前进的每一步都会导致问题,因为您正在针对框架工作。示例:要添加或删除项目,您必须使整个部分无效。 OP 应该保持多少行,即使他设法维护了一个自定义的 flowlayout 类。用行替换 2。是的,删除一个新单元格需要使所有部分无效,而 OP 没有要求它。除非不能有效地涵盖用例,否则解决方案并不肮脏。 时间 == $$,所以有时快速而肮脏也可以。 UICollectionViewLayout 的好处在于它将安排单元格的责任与其他任务分开。这种方法破坏了这种设计,并使数据源负责事后猜测布局将做什么,从而使您的代码更不灵活且更脆弱。例如,如果您有一个以列为主的流布局对象,您可以通过交换不同的布局轻松更改您的集合;这样,更改布局意味着重写数据源。这可能没问题——如果你愿意付出代价。

以上是关于UICollectionView“流向”的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 比 NavigationController 大

UICollectionView cellForRow 崩溃

滚动 UICollectionView 时保留 UICollectionViewCell

UICollectionView - 分离 scrollViewDidScroll 和 scrollToItemAtIndexPath

以编程方式创建 UICollectionView

从 UICollectionview 隐藏部分