【问题标题】:How to set cell spacing and UICollectionView - UICollectionViewFlowLayout size ratio?如何设置单元格间距和 UICollectionView - UICollectionViewFlowLayout 大小比例?
【发布时间】:2015-04-04 04:55:21
【问题描述】:

我正在尝试将UICollectionView 添加到ViewController,并且我需要“每行”有 3 个单元格,单元格之间没有空格(它应该看起来像一个网格)。单元格宽度应该是屏幕大小的三分之一,所以我认为layout.item 宽度应该是一样的。但后来我明白了:

如果我减小该尺寸(例如减小 78 像素),效果会更好,但行中的第三个单元格不完全可见,我仍然有那个空格(上下、左右)。

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    var collectionView: UICollectionView?
    var screenSize: CGRect!
    var screenWidth: CGFloat!
    var screenHeight: CGFloat!

    override func viewDidLoad() {
        super.viewDidLoad()

        screenSize = UIScreen.mainScreen().bounds
        screenWidth = screenSize.width
        screenHeight = screenSize.height

        // Do any additional setup after loading the view, typically from a nib
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
        layout.itemSize = CGSize(width: screenWidth / 3, height: screenWidth / 3)
        collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        collectionView!.dataSource = self
        collectionView!.delegate = self
        collectionView!.registerClass(CollectionViewCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
        collectionView!.backgroundColor = UIColor.greenColor()
        self.view.addSubview(collectionView!)
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as CollectionViewCell
        cell.backgroundColor = UIColor.whiteColor()
        cell.layer.borderColor = UIColor.blackColor().CGColor
        cell.layer.borderWidth = 0.5
        cell.frame.size.width = screenWidth / 3
        cell.frame.size.height = screenWidth / 3

        cell.textLabel?.text = "\(indexPath.section):\(indexPath.row)"
        return cell
    }
}

【问题讨论】:

标签: swift uicollectionview uicollectionviewcell uicollectionviewlayout


【解决方案1】:

添加这两行

layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0

所以你有:

   // Do any additional setup after loading the view, typically from a nib.
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
        layout.itemSize = CGSize(width: screenWidth/3, height: screenWidth/3)
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0
        collectionView!.collectionViewLayout = layout

这将删除所有空格并为您提供网格布局:

如果您希望第一列的宽度等于屏幕宽度,请添加以下函数:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    if indexPath.row == 0
    {
        return CGSize(width: screenWidth, height: screenWidth/3)
    }
    return CGSize(width: screenWidth/3, height: screenWidth/3);

}

网格布局现在看起来像(我还在第一个单元格中添加了蓝色背景):

【讨论】:

  • 非常感谢,我期待更复杂的事情,我花了很多时间。再次感谢。
  • 还有一件事,是否有可能仅更改第一个单元格的 layout.itemSize ? (我知道当 indexPath.row 为 0 时我需要更改 cell.frame.size,但不知道如何仅更改一项的布局大小)第一个元素宽度应该等于 屏幕宽度.
  • 嗨,我有同样的问题,但我想知道 Objective C 中类似的函数标题。
  • 好的,现在工作正常,非常感谢:) Objective C 函数:-(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:( NSIndexPath *)indexPath { return CGSizeMake(screenWidth/3, screenWidth/3); }
  • 感谢@greentor 的精彩回答。送了赏金。别忘了collectionView!.collectionViewLayout = layout,读者们
【解决方案2】:

对于 Swift 3 和 XCode 8,这很有效。请按照以下步骤实现:-

{
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    let width = UIScreen.main.bounds.width
    layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    layout.itemSize = CGSize(width: width / 2, height: width / 2)
    layout.minimumInteritemSpacing = 0
    layout.minimumLineSpacing = 0
    collectionView!.collectionViewLayout = layout
}

将此代码放入 viewDidLoad() 函数中。

【讨论】:

    【解决方案3】:

    对于 Swift 3 和 XCode 8, 这很有效。请按照以下步骤实现:-

    viewDidLoad()
        {
            let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            var width = UIScreen.main.bounds.width
            layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
        width = width - 10
        layout.itemSize = CGSize(width: width / 2, height: width / 2)
            layout.minimumInteritemSpacing = 0
            layout.minimumLineSpacing = 0
            collectionView!.collectionViewLayout = layout
        }
    

    【讨论】:

    • 如果您有多个部分,如何考虑这一事实
    • 仅1列(节)
    【解决方案4】:

    如果您正在寻找 Swift 3,请按照以下步骤实现:

    func viewDidLoad() {
    
        //Define Layout here
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    
        //Get device width
        let width = UIScreen.main.bounds.width
    
        //set section inset as per your requirement.
        layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    
        //set cell item size here 
        layout.itemSize = CGSize(width: width / 2, height: width / 2)
    
        //set Minimum spacing between 2 items
        layout.minimumInteritemSpacing = 0
    
        //set minimum vertical line spacing here between two lines in collectionview
        layout.minimumLineSpacing = 0
    
        //apply defined layout to collectionview
        collectionView!.collectionViewLayout = layout
    
    }
    

    这在带有 Swift 3 的 Xcode 8.0 上得到验证。

    【讨论】:

      【解决方案5】:

      在某些情况下,在viewDidLoadViewWillAppear中设置UICollectionViewFlowLayout可能不会影响collectionView。

      viewDidAppear 中设置UICollectionViewFlowLayout 可能会导致在运行时看到单元格大小的变化。

      另一个解决方案,在 Swift 3 中:

      extension YourViewController : UICollectionViewDelegateFlowLayout{
      
          func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
              return UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
          }
      
          func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
              let collectionViewWidth = collectionView.bounds.width
              return CGSize(width: collectionViewWidth/3, height: collectionViewWidth/3)
          }
      
          func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
              return 0
          }
          func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
              return 20
          }
      }
      

      【讨论】:

      • 很好的答案!这绝对是 Apple 的做法。现在,您不会碰巧知道当设备改变方向时如何刷新,是吗?
      【解决方案6】:
      let layout = myCollectionView.collectionViewLayout as? UICollectionViewFlowLayout
      layout?.minimumLineSpacing = 8
      

      【讨论】:

        【解决方案7】:

        斯威夫特 4

        let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
        collectionViewLayout?.sectionInset = UIEdgeInsetsMake(0, 20, 0, 40) 
        collectionViewLayout?.invalidateLayout()
        

        【讨论】:

        • 为什么设置后布局失效?
        【解决方案8】:

        对于 Swift 3+ 和 Xcode 9+ 试试这个

        extension ViewController: UICollectionViewDelegateFlowLayout {
        
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
            let collectionWidth = collectionView.bounds.width
            return CGSize(width: collectionWidth/3, height: collectionWidth/3)
        
        }
        
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
            return 0
        }
        
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
            return 0
        
        }
        

        【讨论】:

          【解决方案9】:

          Swift 5 :对于具有动态单元格宽度的单元格之间的均匀分布空间以充分利用容器空间,您可以通过提供 minimumCellWidth 来使用下面的代码 sn-p价值。

          private func collectionViewLayout() -> UICollectionViewLayout {
              
              let layout = UICollectionViewFlowLayout()
              layout.sectionHeadersPinToVisibleBounds = true
              // Important: if direction is horizontal use minimumItemSpacing instead. 
              layout.scrollDirection = .vertical
              
              let itemHeight: CGFloat = 240
              let minCellWidth :CGFloat = 130.0
              let minItemSpacing: CGFloat = 10
              let containerWidth: CGFloat = self.view.bounds.width
              let maxCellCountPerRow: CGFloat =  floor((containerWidth - minItemSpacing) / (minCellWidth+minItemSpacing ))
              
              let itemWidth: CGFloat = floor( ((containerWidth - (2 * minItemSpacing) - (maxCellCountPerRow-1) * minItemSpacing) / maxCellCountPerRow  ) )
              // Calculate the remaining space after substracting calculating cellWidth (Divide by 2 because of left and right insets)
              let inset = max(minItemSpacing, floor( (containerWidth - (maxCellCountPerRow*itemWidth) - (maxCellCountPerRow-1)*minItemSpacing) / 2 ) )
          
              
              layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
              layout.minimumInteritemSpacing = min(minItemSpacing,inset)
              layout.minimumLineSpacing = minItemSpacing
              layout.sectionInset = UIEdgeInsets(top: minItemSpacing, left: inset, bottom: minItemSpacing, right: inset)
          
              
              return layout
          }
          

          【讨论】:

            【解决方案10】:

            Swift 4,Swift 5,最简单的方法!

            无需创建UICollectionViewFlowLayout() 实例,只需在您的类上实现UICollectionViewDelegateFlowLayout

            extension MyCollectionView: UICollectionViewDelegateFlowLayout {
            
                // Distance Between Item Cells
                func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
                    return 20
                }
                
                // Cell Margin
                func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
                    return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
                }
            
            }
            

            【讨论】:

              【解决方案11】:

              我们不用写一行代码,而是在 XCode 中有一个选项,选择 CollectionView 并转到导航器并更改 "Min Spacing"

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2015-05-01
                • 1970-01-01
                • 1970-01-01
                • 2021-08-10
                • 2021-12-13
                • 2013-10-15
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多