我正在尝试将UICollectionView设置为两行的水平菜单
我试图提供标签尺寸。但是缩进太多。
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let tagName = tags[indexPath.row].tag?.name ?? ""
let size: CGSize = tagName.size(withAttributes: [.font: UIFont.systemFont(ofSize: 13)])
return CGSize(width: size.width + 52, height: 34)
}
此代码给了我很多缩进:
我需要这样的最终结果:
[ⅩⅩⅩⅩ] [XXXXXXXXX] [XXXXXXXXXX] [XXXXXX]
[XXXXXXXXX] [XXXXXXXX] [XXXXXX] [XXX]
我找到了解决方案。根据列的宽度为每列声明xOffset
数组并用其x坐标填充。 yOffset
数组跟踪每一列的y位置。
protocol SelfSizingHorizontallyCustomLayoutDelegate: AnyObject {
func collectionView(_ collectionView: UICollectionView, widthForCellAtIndexPath indexPath: IndexPath) -> CGFloat
}
class SelfSizingHorizontallyCustomLayout: UICollectionViewLayout {
weak var delegate: SelfSizingHorizontallyCustomLayoutDelegate?
private let numberOfColumns = 2
private let cellPadding: CGFloat = 6
private var cache: [UICollectionViewLayoutAttributes] = []
private var contentWidth: CGFloat = 0
private var contentHeight: CGFloat {
guard let collectionView = collectionView else {
return 0
}
let insets = collectionView.contentInset
return collectionView.bounds.height - (insets.top + insets.bottom)
}
override var collectionViewContentSize: CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
override func prepare() {
guard cache.isEmpty, let collectionView = collectionView else { return }
let columnHeight = contentHeight / CGFloat(numberOfColumns)
var yOffset: [CGFloat] = []
for column in 0..<numberOfColumns {
yOffset.append(CGFloat(column) * columnHeight)
}
var column = 0
var xOffset: [CGFloat] = .init(repeating: 0, count: numberOfColumns)
for item in 0..<collectionView.numberOfItems(inSection: 0) {
let indexPath = IndexPath(item: item, section: 0)
let cellWidth = delegate?.collectionView(collectionView, widthForCellAtIndexPath: indexPath) ?? 180
let width = cellPadding * 2 + cellWidth
let frame = CGRect(x: xOffset[column], y: yOffset[column], width: width, height: columnHeight)
let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = insetFrame
cache.append(attributes)
contentWidth = max(contentWidth, frame.maxX)
xOffset[column] = xOffset[column] + width
column = column < (numberOfColumns - 1) ? (column + 1) : 0
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
return visibleLayoutAttributes
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cache[indexPath.item]
}
}