【问题标题】:Is it possible to create cells with dynamic width but fixed height using Compositional Layout是否可以使用组合布局创建具有动态宽度但固定高度的单元格
【发布时间】:2020-09-10 17:28:14
【问题描述】:

TLDR; 根据部分,我需要调整单元格的大小:

  1. 固定宽度但动态高度(例如,全屏宽度和自动高度取决于内容)
  2. 动态宽度但固定高度(第一个单元格可以是 120pt 宽,第二个单元格可以是 155pt 宽,等等。)

这是我们需要清除可能存在的任何歧义的象形图。

我只是在寻找:“是的,您可以通过组合布局来实现这一点,这就是如何......”。或者“不,你不能用组合来实现这个,你必须使用流布局或其他一些自定义布局。”

几个附加要求:

  1. 建议的解决方案不建议将collectionView(_:layout:sizeForItemAt:) 与流布局一起使用,因为这是我们试图避免的事情。如果这就是答案,那么您可以简单地说 - “不,这无法通过组合布局实现”。
  2. 建议的解决方案应该让集合视图根据单元格的固有内容大小确定如何正确放置单元格。这类似于UITableViewAutomaticDimension 使用 tableview 的动态自调整大小功能

背景信息:

  • 很清楚如何使用组合布局实现全宽但动态高度的单元格。见this exchange
  • herehere 中记录了具有自动内容大小的流布局的已知限制。那是写了O'Reilly books 之一的人。基本上他说没有真正的自动调整流布局,尽管苹果声称有。因此,我们试图通过组合布局来解决这个问题。

【问题讨论】:

  • 您需要在配置单元之前确定单元大小。因此,当您获取单元格的数据之后......但在加载 collectionview 之前......添加一些函数来确定它应该具有的单元格大小(将此数据存储在数组中)。在 UICollectionViewFlowLayoutDelegate 的 sizeForItem 函数中,您可以包含基于 indexpath 引用节和单元格大小的逻辑。
  • 感谢您提供的信息 - 我意识到我的问题并不清楚。我们对使用 FlowLayout 和 collectionView(_:layout:sizeForItemAt:) 委托方法的特定路径不感兴趣。感谢您抽出宝贵时间回复。
  • 别担心!祝你好运,试图通过组合布局来解决这个问题。我认为这是新的,不确定它的可定制性如何。如果您另有决定,我相信您可以使用 sizeForItemAt 轻松完成您想要完成的任务。我一直根据动态内容设置具有不同大小单元格的 collectionViews。干杯

标签: ios swift dynamic uicollectionview uicollectionviewcompositionallayout


【解决方案1】:

您可以使用UICollectionViewCompositionalLayout 构建“第 2 部分”布局。方法如下:

let layoutSize = NSCollectionLayoutSize(
    widthDimension: .estimated(100),
    heightDimension: .absolute(32)
)

let group = NSCollectionLayoutGroup.horizontal(
    layoutSize: .init(
        widthDimension: .fractionalWidth(1.0),
        heightDimension: layoutSize.heightDimension
    ),
    subitems: [.init(layoutSize: layoutSize)]
)
group.interItemSpacing = .fixed(8)

let section = NSCollectionLayoutSection(group: group)
section.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
section.interGroupSpacing = 8

return .init(section: section)

重要的部分是该组使用.fractionalWidth(1.0) 占用可用宽度,但子项具有估计宽度。只需确保您的集合视图单元格可以通过覆盖sizeThatFits(_:)preferredLayoutAttributesFitting(_:) 或使用自动布局来调整大小。结果将是一个如下所示的布局:

要在同一个 UICollectionViewCompositionalLayout 中使用“第 1 节”和“第 2 节”,只需使用 init(sectionProvider:) 创建布局,并在其中为当前节标识符返回适当的 NSCollectionLayoutSection

func createCollectionViewLayout() -> UICollectionViewCompositionalLayout {
    .init(sectionProvider: { [weak self] sectionIndex, _ in
        guard let sectionIdentifier = self?.dataSource.snapshot().sectionIdentifiers[sectionIndex] else { return nil }
        switch sectionIdentifier {
        case .section1: return self?.createSection1()
        case .section2: return self?.createSection2()
        }
    })
}

值得注意的是,如果您的视图控制器在 iOS 13+ 上使用默认的pageSheet 样式呈现,您可能会在此布局中看到一些奇怪的行为。我在这里有一个related question(使用稍微不同的布局)。

【讨论】:

  • 这非常令人鼓舞。我将尝试您的建议并在此处发布结果。感谢您花时间在这里发布答案。我还检查了您的相关问题,很高兴知道。
  • 我很高兴确认这确实有效。我想我会在某个时候写一篇关于它的适当博客。我显然在这里简化了问题以解决问题的症结所在。有机会我会写完整的解决方案。
  • @deniz 你写过博客吗?我需要与您的问题类似的东西,但我的情况不足以转移示例。
  • 嗨@MathiasEgekvist,是的,我确实写了一篇关于它的博客,概括了这里回答的问题。链接是here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 2014-04-17
  • 1970-01-01
  • 2012-08-14
相关资源
最近更新 更多