我正在使用UICollectionViewCompostionalLayout在我的集合视图的某些部分中创建动态宽度、固定高度、标记单元格类型的布局.当我向数据库中的数组添加新字符串、将数组重新加载到数据源并执行集合视图重新加载数据时,单元格以一种不可预测的方式调整大小.有时它们调整大小以适合字符串的宽度,有时它们似乎使用单元格的估计宽度并截断字符串.对如何解决这个问题有什么建议吗?我已经在下面发布了一张gif.

enter image description here

以下是我的makelayout函数(简化并删除了不必要的代码行):

override func makeLayout() -> UICollectionViewLayout {
        let layout = UICollectionViewCompositionalLayout(sectionProvider: { (sectionIndex, environment) -> NSCollectionLayoutSection? in


        let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(40), heightDimension: .absolute(40))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let inset: CGFloat = 10
        item.contentInsets = NSDirectionalEdgeInsets(top: inset, leading: inset, bottom: inset, trailing: inset)
            
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(40))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        group.interItemSpacing = NSCollectionLayoutSpacing.fixed(CGFloat(10))
        let section = NSCollectionLayoutSection(group: group)
        section.interGroupSpacing = CGFloat(10.0)
        section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)
        section.supplementariesFollowContentInsets = false

        return section
          
    })
        
        
    let config = UICollectionViewCompositionalLayoutConfiguration()
    config.scrollDirection = .vertical
    config.interSectionSpacing = 10
    layout.configuration = config
      
    return layout
}

这是我自定义集合视图单元格

class CollectionViewCell: UICollectionViewCell {
    
    lazy var textLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont(name: "Stolzl-Regular", size: 12)
        label.textAlignment = NSTextAlignment.left
        label.backgroundColor = .clear //.red
        label.textColor = .white
        label.text = ""
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)

        setupLabel()

    }
    
    func setupLabel(){
        addSubview(textLabel)
        addConstraintsWithFormat("H:|-10-[v0]-10-|", views: textLabel)
        addConstraintsWithFormat("V:|-10-[v0]-10-|", views: textLabel)
    }

    override func prepareForReuse() {
        super.prepareForReuse()

    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

推荐答案

我们显然不知道苹果是如何决定实施.estimated(n)种布局机制的.如果我们能看到他们的代码,我们可能就能准确地确定这里发生了什么.但我过go 在我自己的应用程序中也看到过类似的UI布局问题.我认为问题出在以下代码行之间的相互作用中:

let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(40),  heightDimension: .absolute(40)).
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping

你本质上是在限制你的单元格.A)您的标签上允许无限数量的行.B)您还允许线路为broken by words行.C)此外,您告诉布局引擎您不知道单元格(或标签--因为这是单元格中唯一的东西)的大小.重新加载视图后,截断的标签也满足了您对它们施加的约束,尽管这可能不是您的意图.

当约束不明确时,有多种方法来满足约束.看起来,在第一次布局过程中,布局引擎 Select 一种方法来满足这些约束,而当您重新加载集合视图时,布局引擎 Select 另一种方法.理想情况下,布局引擎是一致的,并且始终使用相同的方法来执行布局.这可能就是问题所在.我认为,如果您将number OfLines属性切换为1,并将NSLineBreakMode切换为byTruncatingTail,我猜您将拥有更一致的布局体验.

我还建议调整你的估计大小,因为它应该接近你细胞的平均大小.从你的gif中的表视图来看你可能的值-我可以告诉你40分太小了.也许120分是一个更现实的估计.

Swift相关问答推荐

为表单部分赋予背景 colored颜色 /渐变

编写Swift字符串的属性包装时遇到问题

为SwiftUI文本视图提供固定宽度,并仅在文本换行时使文本视图底部增大

background Task(.backgroundTask)不适用于MySQL

从SwiftUI使用UIPageView时,同一页面连续显示两次的问题

如何在 swiftui 中设置给定字符串类型日期的日期倒计时?

防止带有背景的文本扩展到 maxWidth

Swiftui 无法从核心数据中获取数据

如何测试可选 struct 的协议一致性

使用泛型的 Swift 枚举值

Swift:创建用于调用 C 函数的指针数组

将基于MyProtocol的泛型函数的参数更改为使用存在的any MyProtocol或some MyProtocol是否会受到惩罚?

在 Swift 中实现自定义异步序列

`IndexSet` 永远不会是空的?

Swift 2.0 最低系统版本要求(部署目标)

WKWebView 确实从本地文档文件夹加载资源

Swift 中的可选数组与空数组

在 xcode8 中找不到 ModuleName-Swift.h 文件

Swift 5 秒后关闭 UIAlertView

通过单击表格视图中的单元格打开新的视图控制器 - Swift iOS