swift - 自定义 UICollectionViewLayout 中的自定义标题
问题描述
我试图实现这个用户界面:
来自本教程https://www.raywenderlich.com/4829472-uicollectionview-custom-layout-tutorial-pinterest
我已经能够嵌套 2 个具有不同滚动方向的 collectionView:
但现在我坚持为每个部分添加 2 个自定义 headerView。我确实看过这个问题并尝试根据它修改我的代码,但效果不佳:
我得到了什么:
如您所见,仅显示 1 个标题(预期为 2),并且与单元格重叠。
这是标题的代码:
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: HeaderHomeView.identifier, for: indexPath) as? HeaderHomeView
return header!
}
//Inside custom UICollectionViewLayout
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
// Loop through the cache and look for items in the rect
let sectionsCount = self.collectionView!.dataSource!.numberOfSections!(in: self.collectionView!)
for section in 0..<sectionsCount {
visibleLayoutAttributes.append(self.layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: NSIndexPath(item: 0, section: section) as IndexPath)!)
}
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
return visibleLayoutAttributes
}
override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: indexPath as IndexPath)
attributes.frame = CGRect(x: 0, y: 0, width: contentWidth, height: 100)
return attributes
}
编辑:我尝试了print
每一个UICollectionViewLayoutAttributes
,似乎我必须计算x,y
每个标题的值,但我仍然没有弄清楚。
<UICollectionViewLayoutAttributes: 0x7f833f93b3f0> index path: (<NSIndexPath: 0xb3260380861bce99> {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 358 100);
<UICollectionViewLayoutAttributes: 0x7f833f93b550> index path: (<NSIndexPath: 0xb3260380861bcf99> {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 358 100);
<UICollectionViewLayoutAttributes: 0x7f833f93ac60> index path: (<NSIndexPath: 0xb3260380861bce99> {length = 2, path = 0 - 0}); frame = (6 6; 346 100);
<UICollectionViewLayoutAttributes: 0x7f833f939360> index path: (<NSIndexPath: 0xb3260380861bcf99> {length = 2, path = 1 - 0}); frame = (6 118; 167 292);
<UICollectionViewLayoutAttributes: 0x7f833f9394c0> index path: (<NSIndexPath: 0xb3260380863bcf99> {length = 2, path = 1 - 1}); frame = (185 118; 167 328);
这是我的自定义 UICollectionViewLayOut 的完整代码
class PinterestLayout: UICollectionViewLayout {
// 1
weak var delegate: PinterestLayoutDelegate?
// 2
var numberOfColumns = 2
private let cellPadding: CGFloat = 6
// 3
private var cache: [UICollectionViewLayoutAttributes] = []
// 4
private var contentHeight: CGFloat = 0
private var contentWidth: CGFloat {
guard let collectionView = collectionView else {
return 0
}
let insets = collectionView.contentInset
return collectionView.bounds.width - (insets.left + insets.right)
}
// 5
override var collectionViewContentSize: CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
override func prepare() {
// 1
guard
cache.isEmpty == true,
let collectionView = collectionView
else {
return
}
// 2
let columnWidth = contentWidth / CGFloat(numberOfColumns)
var xOffset: [CGFloat] = []
for column in 0..<numberOfColumns {
xOffset.append(CGFloat(column) * columnWidth)
}
var column = 0
var yOffset: [CGFloat] = .init(repeating: 0, count: numberOfColumns)
// 3
for section in 0..<collectionView.numberOfSections {
for item in 0..<collectionView.numberOfItems(inSection: section) {
let indexPath = IndexPath(item: item, section: section)
let attributes: UICollectionViewLayoutAttributes
let photoHeight = delegate?.collectionView(
collectionView,
heightForPhotoAtIndexPath: indexPath) ?? 180
let height = cellPadding * 2 + photoHeight
let frame: CGRect
if section == 0 {
frame = CGRect(x: 0,
y: yOffset[column],
width: contentWidth,
height: height)
contentHeight = frame.maxY
for column in 0..<numberOfColumns {
yOffset[column] = frame.maxY
}
column = 0
} else {
// 4
frame = CGRect(x: xOffset[column],
y: yOffset[column],
width: columnWidth,
height: height)
contentHeight = max(contentHeight, frame.maxY)
yOffset[column] = yOffset[column] + height
column = column < (numberOfColumns - 1) ? (column + 1) : 0
}
let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = insetFrame
cache.append(attributes)
}
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
// Loop through the cache and look for items in the rect
let sectionsCount = self.collectionView!.dataSource!.numberOfSections!(in: self.collectionView!)
for section in 0..<sectionsCount {
visibleLayoutAttributes.append(self.layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: NSIndexPath(item: 0, section: section) as IndexPath)!)
}
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
for each in visibleLayoutAttributes {
print("\(each)\n")
}
return visibleLayoutAttributes
}
override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: indexPath as IndexPath)
attributes.frame = CGRect(x: 0, y: 0, width: contentWidth, height: 100)
return attributes
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cache[indexPath.item]
}
}
解决方案
推荐阅读
- python - Selenium webdriver 超时后停止
- javascript - 如何向这个 js 文件添加状态构造函数?
- webpack - 带有 img 应答器的 Webpack ejs 加载器
- charts - 谷歌图表工具栏:从谷歌图表工具栏实时数据导出
- reactjs - 在 ReactJS 中使用 Fetch 进行 POST 调用(带有标头和请求正文)
- geometry - 是否有一些算法可以匹配来自候选多边形集的多边形?
- php - 如何在 PHP 中获取 Typo3 模板常量的值?
- php - 将图像转换为背景图像
- sql-server - 如何使用 SSIS 压缩文件,然后转到 Azure 数据湖(无需先导出平面文件)
- php - 在 html 视频源中需要在特定时间播放视频