动态UICollectionViewCell宽度相对于帧宽和宽高比

the*_*net 0 dynamic uicollectionview uicollectionviewcell uicollectionviewlayout swift

这是来自UICollectionViewCell动态调整4.4和5.5英寸的后续问题

虽然这个解决方案很棒,但我想根据设备的宽度,宽高比和我必须显示的总项目数量在UIVIewController中生成动态数量的项目单元格(kCellsPerRow).我只是无法弄清楚如何计算正确数量的kCellsPerRow,以便一旦达到宽高比限制它们就不会过于调整大小.

这是我到目前为止所拥有的:

var kCellsPerRow = ceil(global.TotalAmount)                //Total Amount of Cells
var windowWidth = layout.collectionView!.frame.width        // Device's Window Width 
var dynamicWidth = windowWidth / CGFloat(kCellsPerRow)    // Current Width of Each Cell
var dynamicHeight = windowWidth / CGFloat(kCellsPerRow)    // Current Height of Each Cell
var limit = (Double(dynamicWidth) / Double(windowWidth))*(9/2) < (2/9)    // Constraint/Threshold

if ( limit ) {
    var newkCellsPerRow = CGFloat(kCellsPerRow * (2/9))    // Attempt
    newkCellsPerRow = 9  // Fixed Size of 9 but what if we can dynamically figure out the perfect number such that its not so tiny!

    dynamicWidth = layout.collectionView!.frame.width / newkCellsPerRow
    dynamicHeight = layout.collectionView!.frame.width / newkCellsPerRow
}

// Create Cell
layout.itemSize = CGSize(width: dynamicWidth, height: dynamicHeight)
Run Code Online (Sandbox Code Playgroud)

小智 5

您需要指定的是单元格应该具有的最小尺寸.细胞将至少与该尺寸一样宽(和高),并且可能更大.

做法:

这是一个方法,它将根据其collectionView的宽度计算适当的单元格大小:

// These variables are set in the Storyboard, but shown here for clarity
flowLayout.minimumInteritemSpacing = 10
flowLayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)

let minimumSize: CGFloat = 90.0 // A cell's width or height won't ever be smaller than this

func cellWidthForViewWidth(viewWidth: CGFloat) -> CGFloat {
    // Determine the largest number of cells that could possibly fit in a row, based on the cell's minimum size
    var numberOfCellsPerRow = Int(viewWidth / minimumSize)

    // Adjust for interitem spacing and section insets
    let availableWidth = viewWidth - flowLayout.sectionInset.left - flowLayout.sectionInset.right - flowLayout.minimumInteritemSpacing * CGFloat(numberOfCellsPerRow - 1)
    numberOfCellsPerRow = Int(availableWidth / minimumSize)

    return availableWidth / CGFloat(numberOfCellsPerRow) // Make this an integral width if desired
}
Run Code Online (Sandbox Code Playgroud)

处理非1:1宽高比:

如果纵横比恰好与1:1不同,则只需将计算出的宽度除以纵横比即可确定动态高度.

let aspectRatio: CGFloat = 3.0/2.0
let cellWidth = cellWidthForViewWidth(CGRectGetWidth(collectionView.frame))
let cellHeight = cellWidth / aspectRatio
Run Code Online (Sandbox Code Playgroud)

设置项目大小:

由于宽高比为1:1,我们只需要计算单元格的宽度,然后将该值用于宽度和高度.

根据计算的动态大小设置实际项目大小:

let actualCellSize = cellWidthForViewWidth(CGRectGetWidth(collectionView.frame))
flowLayout.itemSize = CGSize(width: actualCellSize, height: actualCellSize)
Run Code Online (Sandbox Code Playgroud)

样品结果:

这将根据各种容器宽度让您了解单元格的大小:

print(cellWidthForViewWidth(320.0))  //  93,  3 cells per row
print(cellWidthForViewWidth(400.0))  // 116,  3 cells per row
print(cellWidthForViewWidth(640.0))  //  93,  6 cells per row
print(cellWidthForViewWidth(800.0))  // 101,  7 cells per row
print(cellWidthForViewWidth(1024.0)) //  90, 10 cells per row
Run Code Online (Sandbox Code Playgroud)