如何通过自动布局设置集合视图单元格大小

Posted

技术标签:

【中文标题】如何通过自动布局设置集合视图单元格大小【英文标题】:How do I set collection view's cell size via the auto layout 【发布时间】:2016-06-25 04:56:40 【问题描述】:

您好,我正在尝试通过 auto layout 调整单元格的大小。

我想按 3 x 3 显示单元格。

第一个单元格的左边距=0

Last Cell 的右边距=0

并且所有单元格的空间都有 1pt。喜欢instagram

我应该设置单元格的大小吗?我想通过自动布局设置约束。

我也尝试使用代码设置单元格的大小。

这是我的代码:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize 
    return CGSizeMake(123, 123);


func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat 
    return 1;


func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat 
    return 1;

但是..我认为它不是精确计算单元格的大小。

如何根据屏幕大小设置单元格大小?

我必须在单元格之间设置 1pt 的空间。

有没有只使用情节提要设置?

如果没有,我如何通过代码设置?

谢谢。

【问题讨论】:

谢谢!效果很好。 【参考方案1】:

我不相信您可以仅使用情节提要来设置大小,因为您无法为重复项目设置约束,例如在运行时动态创建的集合视图单元格。

您可以根据提供的信息轻松计算大小。在collectionView(_:layout:sizeForItemAt:) 中,您可以访问collectionView 的边界来计算所需的单元格大小:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    // Compute the dimension of a cell for an NxN layout with space S between
    // cells.  Take the collection view's width, subtract (N-1)*S points for
    // the spaces between the cells, and then divide by N to find the final
    // dimension for the cell's width and height.

    let cellsAcross: CGFloat = 3
    let spaceBetweenCells: CGFloat = 1
    let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross
    return CGSize(width: dim, height: dim)

确保您的班级采用协议UICollectionViewDelegateFlowLayout

这适用于各种尺寸的 iPhone 和 iPad。

【讨论】:

集合视图单元格现在不支持自动调整大小吗? 我不知道@ThuggishNuggets。您必须以某种方式提供与我在这里处理的相同类型的信息,例如跨单元格的数量和单元格之间的所需间距。如果您知道另一种或更好的方法,请添加答案。 非常感谢~! 我只是让差距稍大一点,以使差异不那么明显。 @vacawama 我明白感谢您的帮助。我真的很感谢你:)【参考方案2】:

vacawama 的回答很好,但我有 2 个问题。我希望自动使用我在情节提要中定义的间距。

其次,我无法调用此函数,也没有人提到如何调用?为了调用 collectionView 的 sizeForItemAt,您需要扩展 UICollectionViewDelegateFlowLayout 而不是扩展 UICollectionViewDelegate。我希望这可以节省其他人一些时间。

extension MyViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
        let cellsAcross: CGFloat = 3
        var widthRemainingForCellContent = collectionView.bounds.width
        if let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout 
            let borderSize: CGFloat = flowLayout.sectionInset.left + flowLayout.sectionInset.right
            widthRemainingForCellContent -= borderSize + ((cellsAcross - 1) * flowLayout.minimumInteritemSpacing)
        
        let cellWidth = widthRemainingForCellContent / cellsAcross
        return CGSize(width: cellWidth, height: cellWidth)
    


【讨论】:

【参考方案3】:

我使用 CollectionView 的委托方法设置它。这将为您提供 2xN 设置,但您可以轻松地将其设置为 3xN。这是一个截图,你可以参考我在 GitHub 上的项目...

https://github.com/WadeSellers/GoInstaPro

【讨论】:

【参考方案4】:

Swift 3 版本代码基于 vacawama 答案:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 

        let cellsAcross: CGFloat = 3
        let spaceBetweenCells: CGFloat = 1
        let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross

        return CGSize(width: dim, height: dim)
    

【讨论】:

【参考方案5】:

这是另一种解决方案,但它只适用于 iPhone6。

我会尝试为 iphone5/6plus 更新

特别感谢@vacawama!

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize 
        
        
        // Compute the dimension of a cell for an NxN layout with space S between
        // cells.  Take the collection view's width, subtract (N-1)*S points for
        // the spaces between the cells, and then divide by N to find the final
        // dimension for the cell's width and height.
        
        let cellsAcross: CGFloat = 3
        let spaceBetweenCells: CGFloat = 1
        let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross
                print(indexPath.row)
        
        var width = dim
        
        //last cell's width
        if(  (indexPath.row + 1) % 3 == 0)
            width = 124
            
        else 
            width = 124.5
        
        print(width)
        return CGSize(width: width , height: dim)
        
    
    
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat 
        return 1;
    
    
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat 
        return 1;
    

【讨论】:

以上是关于如何通过自动布局设置集合视图单元格大小的主要内容,如果未能解决你的问题,请参考以下文章

无法使用自动布局将简单的自行调整大小的集合视图单元格调整为标签大小

集合视图单元格的自动布局行为怪异

如何使用自动布局来调整表格视图单元格中的视图大小?

具有动态大小的单元格的复杂自动布局

使用自动布局约束动态调整表格视图单元格的大小

仅通过自动布局确定 UICollectionView 单元格高度