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

UICollectionViewCompositionalLayout是否支持手动计算宽高并动态修改NSCollectionLayoutSize?

解决方案

UICollectionViewCompositionalLayout 完全支持手动指定精确尺寸,无需被迫使用预估布局,动态修改 NSCollectionLayoutSize 可以通过以下两种方案实现,完美匹配你提前计算尺寸存储在ViewModel的使用习惯:

方案1:基于Section维度动态配置尺寸

使用 UICollectionViewCompositionalLayout 的闭包构造器 init(sectionProvider:),在闭包中根据当前Section的索引,读取ViewModel中提前计算好的对应Section配置,生成对应的布局参数即可,示例代码如下:

let layout = UICollectionViewCompositionalLayout { [weak self] sectionIndex, layoutEnvironment in
    guard let self = self, let currentSectionVM = self.viewModel.sections[sectionIndex] else {
        // 异常场景返回默认占位布局
        let defaultSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(44))
        let item = NSCollectionLayoutItem(layoutSize: defaultSize)
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: defaultSize, subitems: [item])
        return NSCollectionLayoutSection(group: group)
    }
    
    // 直接读取VM中提前计算好的尺寸
    let itemSize = NSCollectionLayoutSize(
        widthDimension: .absolute(currentSectionVM.itemFixedWidth),
        heightDimension: .absolute(currentSectionVM.itemFixedHeight)
    )
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    
    // 可根据业务配置设置横向滚动逻辑
    let groupSize = NSCollectionLayoutSize(
        widthDimension: currentSectionVM.enableHorizontalScroll ? .absolute(currentSectionVM.contentTotalWidth) : .fractionalWidth(1),
        heightDimension: .absolute(currentSectionVM.sectionFixedHeight)
    )
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    
    let section = NSCollectionLayoutSection(group: group)
    if currentSectionVM.enableHorizontalScroll {
        section.orthogonalScrollingBehavior = .continuous
    }
    return section
}

方案2:同一Section下不同Item动态配置尺寸

如果同一个Section内不同Item的尺寸存在差异,可以使用 NSCollectionLayoutGroup 的 init(layoutSize:itemProvider:) 构造器,在itemProvider闭包中根据当前Item的索引读取ViewModel中预存的尺寸,生成对应的Item布局:

let group = NSCollectionLayoutGroup.horizontal(
    layoutSize: groupSize,
    itemProvider: { [weak self] itemIndex, layoutEnvironment in
        guard let self = self, let currentItemVM = currentSectionVM.items[itemIndex] else {
            return NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .absolute(0), heightDimension: .absolute(0)))
        }
        // 读取提前计算好的单个Item尺寸
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .absolute(currentItemVM.preCalculatedWidth),
            heightDimension: .absolute(currentItemVM.preCalculatedHeight)
        )
        return NSCollectionLayoutItem(layoutSize: itemSize)
    }
)

注意事项

  • 上述两种方案均使用绝对尺寸,不需要开启估算逻辑,布局只会在数据刷新时读取一次ViewModel中的预计算尺寸,滑动过程中不会重复计算,和你之前使用YYKit布局的性能表现一致
  • 后续如果需要更新某个Item/Section的尺寸,只要修改ViewModel中对应的预计算值,调用UICollectionView的刷新接口即可,布局会自动读取最新的尺寸配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 06:24:04