【问题标题】:UICollectionView spacing marginsUICollectionView 间距边距
【发布时间】:2012-12-07 21:37:33
【问题描述】:

我有一个显示照片的UICollectionView。我使用UICollectionViewFlowLayout 创建了collectionview。它工作得很好,但我想在边距上有间距。是否可以使用UICollectionViewFlowLayout 来做到这一点,还是我必须实现自己的UICollectionViewLayout

【问题讨论】:

    标签: ios uicollectionview uikit


    【解决方案1】:

    现代 Swift,自动布局计算

    虽然这个帖子已经包含了一堆有用的答案,但我想根据 William Hu 的回答添加一个现代 Swift 版本。它还改进了两件事:

    • 现在不同行之间的间距将始终与同一行中项目之间的间距匹配。
    • 通过设置最小宽度, 代码自动计算一行中的项目数,并 将该样式应用于流布局。

    代码如下:

    // Create flow layout
    let flow = UICollectionViewFlowLayout()
    
    // Define layout constants
    let itemSpacing: CGFloat = 1
    let minimumCellWidth: CGFloat = 120
    let collectionViewWidth = collectionView!.bounds.size.width
    
    // Calculate other required constants
    let itemsInOneLine = CGFloat(Int((collectionViewWidth - CGFloat(Int(collectionViewWidth / minimumCellWidth) - 1) * itemSpacing) / minimumCellWidth))
    let width = collectionViewWidth - itemSpacing * (itemsInOneLine - 1)
    let cellWidth = floor(width / itemsInOneLine)
    let realItemSpacing = itemSpacing + (width / itemsInOneLine - cellWidth) * itemsInOneLine / max(1, itemsInOneLine - 1)
    
    // Apply values
    flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    flow.itemSize = CGSize(width: cellWidth, height: cellWidth)
    flow.minimumInteritemSpacing = realItemSpacing
    flow.minimumLineSpacing = realItemSpacing
    
    // Apply flow layout
    collectionView?.setCollectionViewLayout(flow, animated: false)
    

    【讨论】:

    • 如果 itemsInOneLine 为 1,那么这将导致 NaN,因为这里除以零:itemsInOneLine / (itemsInOneLine - 1)
    • @TylerJames 谢谢!我调整了代码来解决这个问题;)
    【解决方案2】:

    斯威夫特 4

        let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout 
        // If you create collectionView programmatically then just create this flow by UICollectionViewFlowLayout() and init a collectionView by this flow.
    
        let itemSpacing: CGFloat = 3
        let itemsInOneLine: CGFloat = 3
        flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    
        //collectionView.frame.width is the same as  UIScreen.main.bounds.size.width here.
        let width = UIScreen.main.bounds.size.width - itemSpacing * CGFloat(itemsInOneLine - 1) 
        flow.itemSize = CGSize(width: floor(width/itemsInOneLine), height: width/itemsInOneLine)
        flow.minimumInteritemSpacing = 3
        flow.minimumLineSpacing = itemSpacing
    

    编辑

    如果要横向改为scrollDirction

    flow.scrollDirection = .horizontal

    注意

    如果您在一行中设置的项目不正确,请检查您的集合视图是否有填充。那就是:

    let width = UIScreen.main.bounds.size.width - itemSpacing * CGFloat(itemsInOneLine - 1)

    应该是collectionView的宽度。

    【讨论】:

    • 有没有办法给间距设置颜色?
    • @MartínDaniel 只需设置collectionViewbackgroundColor。或任何超级视图。
    • 但边缘没有边距
    • @user924 可以使用 UIEdgeInsets 设置边缘的边距(上:左:下:右:)。如果垂直滚动,设置左/右插图。如果水平滚动,设置顶部和底部插入。
    【解决方案3】:

    您可以为您的UICollectionView 使用collectionView:layout:insetForSectionAtIndex: 方法或设置附加到您的UICollectionViewUICollectionViewFlowLayout 对象的sectionInset 属性:

    - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
        return UIEdgeInsetsMake(top, left, bottom, right);
    }
    

    UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    [aFlowLayout setSectionInset:UIEdgeInsetsMake(top, left, bottom, right)];
    

    Swift 5 更新

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
           return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
        }
    

    【讨论】:

    • 在使用垂直流布局时,我似乎无法左右插入工作...
    • 现在重写子类 UICollectionViewFlowLayout 的 sectionInset 方法也没有效果。下面描述的设置属性有效。
    • 注意:记得将 UICollectionViewDelegateFlowLayout 添加到 ViewController 委托列表中以使用方法 insetForSectionAtIndex
    • 我怎样才能为特定的行而不是部分设置这个。
    【解决方案4】:

    设置附加到您的UICollectionViewUICollectionViewFlowLayout 对象的insetForSectionAt 属性

    确保添加此协议

    UICollectionViewDelegateFlowLayout
    

    斯威夫特

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
            return UIEdgeInsets (top: top, left: left, bottom: bottom, right: right)
        }
    

    目标 - C

    - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
        return UIEdgeInsetsMake(top, left, bottom, right);
    }
    

    【讨论】:

      【解决方案5】:

      在 swift 4 和 autoLayout 中,您可以像这样使用 sectionInset

      let layout = UICollectionViewFlowLayout()
              layout.scrollDirection = .vertical
              layout.itemSize = CGSize(width: (view.frame.width-40)/2, height: (view.frame.width40)/2) // item size
              layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10) // here you can add space to 4 side of item
              collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout) // set layout to item
              collectionView?.register(ProductCategoryCell.self, forCellWithReuseIdentifier: cellIdentifier) // registerCell
              collectionView?.backgroundColor = .white // background color of UICollectionView
              view.addSubview(collectionView!) // add UICollectionView to view
      

      【讨论】:

        【解决方案6】:

        在 Objective-C 中

        CGFloat spacing = 5;
        UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*)_habbitCollectionV.collectionViewLayout;
        flow.sectionInset = UIEdgeInsetsMake(0, spacing, 0, spacing);
        CGFloat itemsPerRow = 2;
        CGRect screenRect = [[UIScreen mainScreen] bounds];
        CGFloat oneMore = itemsPerRow + 1;
        CGFloat width = screenRect.size.width - spacing * oneMore;
        CGFloat height = width / itemsPerRow;
        
        flow.itemSize = CGSizeMake(floor(height), height);
        flow.minimumInteritemSpacing = spacing;
        flow.minimumLineSpacing = spacing;
        

        您所要做的就是更改 itemsPerRow 值,它会相应地更新每行的项目数。此外,如果您想要更多或更少的一般间距,您可以更改间距值。

        【讨论】:

        • 很好......它的工作完美。
        【解决方案7】:

        要为指定单元格添加边距,您可以使用此自定义流布局。 https://github.com/voyages-sncf-technologies/VSCollectionViewCellInsetFlowLayout/

        extension ViewController : VSCollectionViewDelegateCellInsetFlowLayout 
        {
            func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemAt indexPath: IndexPath) -> UIEdgeInsets {
                if indexPath.item == 0 {
                    return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
                }
                return UIEdgeInsets.zero
            }
        }
        

        【讨论】:

          【解决方案8】:

          整个上添加间距UICollectionView

          UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) collection.collectionViewLayout;
          flow.sectionInset = UIEdgeInsetsMake(topMargin, left, bottom, right);
          

          使用同一行(水平滚动时为列)的元素之间之间的间距及其大小:

          flow.itemSize = ...;
          flow.minimumInteritemSpacing = ...;
          

          【讨论】:

          • 这行得通,但是collection.collectionViewLayout 需要像@Pooja 的示例中那样进行转换:UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
          • 快速铸造if let flow = collectionViewLayout as? UICollectionViewFlowLayout { flow.itemSize = CGSize(width: 100, height: 100) }
          【解决方案9】:

          使用collectionViewFlowLayout.sectionInsetcollectionView:layout:insetForSectionAtIndex: 是正确的。

          但是,如果您的 collectionView 有多个部分,并且您想为整个 collectionView 添加边距,我建议使用 scrollView contentInset :

          UIEdgeInsets collectionViewInsets = UIEdgeInsetsMake(50.0, 0.0, 30.0, 0.0);
          self.collectionView.contentInset = collectionViewInsets;
          self.collectionView.scrollIndicatorInsets = UIEdgeInsetsMake(collectionViewInsets.top, 0, collectionViewInsets.bottom, 0);
          

          【讨论】:

            【解决方案10】:
            - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
                     return UIEdgeInsetsMake(7, 10, 5, 10);    
               }
            

            【讨论】:

              【解决方案11】:

              要在每个部分之间添加 10px 的间隔,只需编写此代码

              flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);
              

              【讨论】:

              • 当使用 UICollectionElementKindSectionFooter 类型的 UICollectionReusableView 时,您的解决方案将不起作用
              【解决方案12】:

              在 Interface Builder 中设置插入,如下面的屏幕截图所示

              会产生这样的结果:

              【讨论】:

              • 很好的答案,只是想指出您还必须以最小间距进行游戏,以便部分插入效果很好。
              【解决方案13】:

              要在CollectionItems 之间放置空格,请使用此

              在viewdidload中写下这两行

              UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
              collectionViewLayout.sectionInset = UIEdgeInsetsMake(<CGFloat top>, <CGFloat left>, <CGFloat bottom>, <CGFloat right>)
              

              【讨论】:

                【解决方案14】:

                只是为了更正此页面中的一些错误信息:

                1- minimumInteritemSpacing在同一行中的项目之间使用的最小间距。

                默认值:10.0。

                (对于垂直滚动的网格,该值表示同一行中项目之间的最小间距。)

                2- minimumLineSpacing网格中项目行之间使用的最小间距。

                参考:http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewFlowLayout_class/Reference/Reference.html

                【讨论】:

                • 这似乎不会影响部分之间的间距,只影响同一部分中的项目之间的间距?
                • @Crashalot - 你确定你不是指 minimumLineSpacing 吗?即每一行细胞?如果您确实在使用部分,还有部分插入选项。
                • 这对我来说是通过情节提要界面完成的。我一直在寻找仅水平集合视图的解决方案。谢谢+10
                【解决方案15】:

                UICollectionViewFlowLayout-Object 上使用setMinimumLineSpacing:setMinimumInteritemSpacing:

                【讨论】:

                • 不,它不起作用,正如预期的那样。 setMinimumLineSpacing 是:在同一行中的项目之间使用的最小间距。 setMinimumInteritemSpacing 是:网格中项目行之间使用的最小间距。我的问题是关于边距而不是元素之间的空间。例如。第一个元素的左侧和顶部间距。
                • 假设垂直 srollDirection 可以使用 contentInset 作为第一行和最后一行的顶部和底部间距。您也可以在单元格中添加边距。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-10-25
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-01-15
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多