【问题标题】:Collection View Compositional Layout with estimated height not working具有估计高度的集合视图组合布局不起作用
【发布时间】:2020-02-08 20:37:47
【问题描述】:

我希望我的应用针对包括文本大小在内的每个辅助功能选项进行优化。

我根据具有组合布局的部分制作了一个 collectionView 布局。所以我需要我的细胞的高度随着它的内容而增长。我认为使用.estimated(constant) 可以完成这项工作,但它似乎不起作用。内部约束对我来说似乎很好。

这是我正在使用的布局:

let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.42), heightDimension: .estimated(90))
let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(90)))
item.contentInsets = NSDirectionalEdgeInsets(top: 5.0, leading: 12.0, bottom: 5.0, trailing: 12.0)
let group = NSCollectionLayoutGroup.vertical(layoutSize: size, subitem: item, count: 1)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 0.0, leading: 6.0, bottom: 0.0, trailing: 0.0)
section.orthogonalScrollingBehavior = .groupPaging

当我在可访问性设置上设置更高的文本大小时,会发生以下情况:

单元格应该包含 2 个标签,这里是 autoLayoutConstraints :

    NSLayoutConstraint.activate([
        self.titleLabel.topAnchor.constraint(equalTo: self.container.topAnchor, constant: 10),
        self.titleLabel.leftAnchor.constraint(equalTo: self.container.leftAnchor, constant: 20),
        self.titleLabel.rightAnchor.constraint(equalTo: self.container.rightAnchor, constant: -20)
    ])

    NSLayoutConstraint.activate([
        self.subtitleLabel.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 10),
        self.subtitleLabel.leftAnchor.constraint(equalTo: self.container.leftAnchor, constant: 20),
        self.subtitleLabel.rightAnchor.constraint(equalTo: self.container.rightAnchor, constant: -20),
        self.subtitleLabel.bottomAnchor.constraint(equalTo: self.container.bottomAnchor, constant: -10)
    ])

提前感谢您的帮助。

【问题讨论】:

  • 您可能需要收听通知UIContentSizeCategory.didChangeNotification刷新页面。
  • 感谢您的评论。不幸的是,我不愿意在字体更改时收到通知,我试图让 UICollectionViewLayout 足够灵活,不必担心可访问性设置可以正常工作和显示。
  • 当你的约束是完美的,改变label.text可以自动刷新约束,但是目前改变系统字体并不会自动刷新约束,抱歉我没有找到支持这个论点的来源。
  • 问题不是来自标签的约束,而是我给单元格的estimated 高度。如果我错了,请告诉我,但我希望在我的 NSCollectionLayoutDimension 对象中设置为高度的估计值与 UICollectionViewFlowLayout.automaticSize 一样。就像你在这里做的那样:flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

标签: ios swift uicollectionview ios13 ios-autolayout


【解决方案1】:

不确定它是否与系统可访问性相关,但 AFAIK 你不能在项目上使用 .estimated().contentInsets

它有时确实有效,但不可靠。即使在尝试将插图应用于组时,我也在努力争取这一点(虽然它是项目的子类,但我会想象它会起作用):(

【讨论】:

  • 谢谢,你救了我很多!我有一个错误几个小时了!该死的.contentInsents
【解决方案2】:

我发现让我的 LayoutGroup 水平而不是垂直可以解决问题。这是我的最终布局:

        let estimatedHeight = CGFloat(100)
        let layoutSize = NSCollectionLayoutSize(widthDimension: .estimated(200), heightDimension: .estimated(estimatedHeight))
        let item = NSCollectionLayoutItem(layoutSize: layoutSize)
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: layoutSize, subitem: item, count: 1)
        let section = NSCollectionLayoutSection(group: group)
        section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
        section.interGroupSpacing = 10
        section.orthogonalScrollingBehavior = .groupPaging

希望对你有所帮助^^

【讨论】:

  • 哇,绝对不会猜到这一点,但它奏效了。文档太少了。
  • 在 iOS 14 上运行良好!非常感谢?。对于这种 BS,我真的很生气苹果公司,浪费了一天的时间。干杯!
  • 这对我也有用。但是我仍然对为什么这样做感到困惑?我有一个垂直滚动的集合视图,所以理想情况下我应该以垂直方式布局我的组,对吗?这个解决方案似乎已经修复了它,但似乎是一种 hacky 方式。
  • 另外,为什么我使用垂直组时它不起作用? PS:-抱歉问了这么多问题,只是想清楚我的概念:p
【解决方案3】:

在 iOS13+ 上,如果您想创建单元格约束决定单元格高度的布局 - 试试这个:

private func configureCollectionView() {
    collectionView.collectionViewLayout = createLayout()
}

private func createLayout() -> UICollectionViewLayout {
    let layout = UICollectionViewCompositionalLayout {
        (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
        let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(10))
        let item = NSCollectionLayoutItem(layoutSize: size)
        item.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: nil, top: NSCollectionLayoutSpacing.fixed(20), trailing: nil, bottom: NSCollectionLayoutSpacing.fixed(0))
        let group = NSCollectionLayoutGroup.vertical(layoutSize: size, subitems: [item])
        group.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)
        let section = NSCollectionLayoutSection(group: group)
        return section
    }
    return layout
}

确保单元格中的约束、拥抱和压缩阻力具有优先级 - 1000(必需),所有这些:堆栈视图、标签等。

你应该得到这样的东西:

或者如果你想要水平滚动分页,只需添加:

section.orthogonalScrollingBehavior = .groupPaging

到你的部分属性,在布局创建时,你会得到这样的东西:

享受:)

【讨论】:

  • 设置优先内容后可以显示但收藏到导航栏下?。我尝试了所有解决方案,但对我不起作用
【解决方案4】:

为我解决问题的是为项目和组设置相同的高度尺寸

我知道问题的共享代码就是这种情况,@Que20 的解决方案肯定有帮助。但如果问题仍然存在,您可能需要检查一下。


示例

我正在尝试显示一个单元格,其中包含一个固定在单元格边缘的 UIButton。该按钮的高度限制为 44 磅。

最初的尝试

static func mapSection() -> NSCollectionLayoutSection {
    let itemSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(1),
        heightDimension: .fractionalHeight(1)) // Here: a fractional height to the item
    let item = NSCollectionLayoutItem(layoutSize: itemSize)

    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
                                           heightDimension: .estimated(100)) // There: estimated height to the button cell
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

    let section = NSCollectionLayoutSection(group: group)

    return section
}

尽管所有配置都正确,但按钮的高度限制会中断,“估计”变为绝对值。

成功实施

static func mapSection() -> NSCollectionLayoutSection {
    /* 
     Notice that I estimate my button cell to be 500 points high
     It's way too much. But since it's an estimation and we're doing things well,
     it doesn't really matter to the end result.
    */
    let heightDimension = NSCollectionLayoutDimension.estimated(500)

    let itemSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(1),
        heightDimension: heightDimension)
    let item = NSCollectionLayoutItem(layoutSize: itemSize)

    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
                                           heightDimension: heightDimension)
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

    let section = NSCollectionLayoutSection(group: group)

    return section
}

唯一真正的区别在于项目和组都设置为相同的估计高度尺寸。但是现在可以了!

【讨论】:

  • 我简直不敢相信在我做了这么多事情之后,我只需要将我的项目从分数更改为与组相同的估计高度。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 2020-11-02
  • 1970-01-01
  • 2022-07-09
相关资源
最近更新 更多