You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CHTCollectionViewWaterfallLayout时,如何计算网络图片的sizeForItemAt?

解决CHTCollectionViewWaterfallLayout结合SwiftUI卡片的高度计算问题

方案一:继续使用SwiftUI卡片,预计算文本区域高度

SwiftUI的View尺寸可以通过UIHostingController的sizeThatFits方法预计算,无需替换为UIKit,具体步骤如下:

  1. 抽离文本区域为独立SwiftUI View
    把卡片的文本部分单独封装成View,固定宽度为瀑布流的列宽,确保文本自适应布局:
struct CardTextContainer: View {
    let content: String
    let fixedWidth: CGFloat
    
    var body: some View {
        Text(content)
            .font(.system(size: 14))
            .lineLimit(nil)
            .padding(.horizontal, 12)
            .padding(.vertical, 8)
            .frame(width: fixedWidth)
    }
}
  1. 编写文本高度计算函数
    用UIHostingController包裹上述View,调用sizeThatFits获取文本区域的实际高度:
func getTextHeight(for content: String, columnWidth: CGFloat) -> CGFloat {
    let hostVC = UIHostingController(rootView: CardTextContainer(content: content, fixedWidth: columnWidth))
    let fittingSize = hostVC.sizeThatFits(CGSize(width: columnWidth, height: CGFloat.greatestFiniteMagnitude))
    return fittingSize.height
}
  1. 在sizeForItemAt中计算总高度
    结合图片的缩放高度和文本高度,得到cell的完整尺寸,同时建议缓存计算结果避免重复计算:
// 缓存文本高度的字典,key为indexPath.item
private var textHeightCache: [Int: CGFloat] = [:]

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    guard let waterfallLayout = collectionViewLayout as? CHTCollectionViewWaterfallLayout else {
        return CGSize.zero
    }
    // 计算单列宽度:减去内边距和间距
    let columnCount = waterfallLayout.columnCount
    let totalSpacing = waterfallLayout.minimumInteritemSpacing * CGFloat(columnCount - 1)
    let totalInset = waterfallLayout.sectionInset.left + waterfallLayout.sectionInset.right
    let columnWidth = (collectionView.bounds.width - totalSpacing - totalInset) / CGFloat(columnCount)
    
    let item = yourDataSource[indexPath.item]
    
    // 计算图片的显示高度:按列宽等比例缩放
    let imageRatio = item.imageWidth / item.imageHeight
    let imageDisplayHeight = columnWidth / imageRatio
    
    // 获取文本高度(优先用缓存)
    var textHeight: CGFloat
    if let cachedHeight = textHeightCache[indexPath.item] {
        textHeight = cachedHeight
    } else {
        textHeight = getTextHeight(for: item.textContent, columnWidth: columnWidth)
        textHeightCache[indexPath.item] = textHeight
    }
    
    // 总高度 = 图片高度 + 文本区域高度
    let totalHeight = imageDisplayHeight + textHeight
    return CGSize(width: columnWidth, height: totalHeight)
}

方案二:改用UIKit实现卡片(可选)

如果觉得SwiftUI预计算的方式有性能顾虑,可以改用UIKit的UICollectionViewCell,通过AutoLayout约束让文本区域自适应,然后用systemLayoutSizeFitting计算高度:

  1. 构建带AutoLayout的UIKit Cell
    在Cell中添加UIImageView和UILabel,设置约束:图片宽度等于Cell宽度,文本在图片下方、宽度等于Cell宽度,且UILabel的行数设为0。

  2. 计算Cell高度
    在sizeForItemAt中,给Cell的图片和文本赋值,然后调用systemLayoutSizeFitting获取完整高度:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    guard let waterfallLayout = collectionViewLayout as? CHTCollectionViewWaterfallLayout else {
        return CGSize.zero
    }
    let columnWidth = (collectionView.bounds.width - waterfallLayout.minimumInteritemSpacing * CGFloat(waterfallLayout.columnCount - 1) - waterfallLayout.sectionInset.left - waterfallLayout.sectionInset.right) / CGFloat(waterfallLayout.columnCount)
    
    let item = yourDataSource[indexPath.item]
    let cell = YourUICollectionViewCell()
    // 配置图片和文本
    cell.imageView.contentMode = .scaleAspectFit
    cell.imageView.widthAnchor.constraint(equalToConstant: columnWidth).isActive = true
    cell.textLabel.text = item.textContent
    
    // 计算Cell高度
    let fittingSize = cell.systemLayoutSizeFitting(CGSize(width: columnWidth, height: CGFloat.greatestFiniteMagnitude), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
    return CGSize(width: columnWidth, height: fittingSize.height)
}

注意事项

  • 缓存文本/Cell高度能大幅提升列表滚动性能,避免重复计算;如果内容更新,记得清空对应缓存并刷新Cell。
  • 列宽计算要严格考虑瀑布流的内边距、间距和列数,确保和实际布局一致。

内容的提问来源于stack exchange,提问作者pang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 16:03:37