我正在尝试实现这种标签布局(具有动态宽度和高度的集合视图单元格),但是当单元格内标签的文本很长时,代码会因一些约束错误而崩溃。有没有办法让标签具有多行文本和这种布局?如何将单元格的最大宽度限制为组的宽度尺寸并支持多行文本?另外,例如,如果第 3 项的标签(参见图片)将有两行文本,我希望该单元格环绕到第 2 行并占据第 2 行和第 3 行。然后第 4 项应该从第 4 行开始。
如果此布局无法在标签中包含多行文本,我如何将标签中的行数限制为 1,并将标签的宽度限制为组的宽度尺寸,即截断标签中的文本,如果它会在标签中占据不止一行吗?
func makeLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { (section: Int, environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(100), heightDimension: .estimated(32))
let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
let layoutGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: itemSize.heightDimension)
let layoutGroup = NSCollectionLayoutGroup.horizontal(layoutSize: layoutGroupSize, subitems: [layoutItem])
layoutGroup.interItemSpacing = .fixed(8)
let section = NSCollectionLayoutSection(group: layoutGroup)
section.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
section.interGroupSpacing = 8
return section
}
return layout
}
在您的示例中,您的组大小为
.fractionalWidth(1)
- 这意味着它等于该部分的大小。您可以从容器宽度获取此值 - 该值来自初始化 UICollectionViewCompositionalLayout 时的 environment: NSCollectionLayoutEnvironment
参数。
所以你会在你的代码中做这样的事情:
let layout = UICollectionViewCompositionalLayout { (section: Int, environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
//save this width information somewhere in your class
let availableWidth: CGFloat = environment.container.effectiveContentSize.width
...
... //continue to configure your layout normally
}
在显示标签的单元格中,创建最大宽度约束。如果您使用 Interface Builder,请确保约束已连接到 IBOutlet。以下是如何在 Interface Builder 中实现此目的。如果您不使用 IB - 那么在您的代码中执行相同的操作。
当您使用文本配置单元格时,还要配置此最大宽度约束。也许你的 UICollectionViewDelegate 中有这样的东西:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let tagCell = collectionView.dequeueReusableCell(withReuseIdentifier: "tagCellIdentifier", for: indexPath) as? TagCell
let tagData = backingDataSource[indexPath.item] //imagine there is an array named backingDataSource
tagCell.configure(with: tagData, maxWidth: self.availableWidth)
return tagCell
}
最后你的 TagCell 定义如下所示。如果您使用 SwiftUI,则需要将其转换为 SwiftUI。
class TagCell: UICollectionViewCell {
@IBOutlet private weak var tagLabel: UILabel!
@IBOutlet private weak var tagMaxWidthConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
tagLabel.numberOfLines = 2
tagLabel.lineBreakMode = .byTruncatingTail
//configure your label according to your needs
}
...
...
func configure(with tagData: String, maxWidth: CGFloat) {
self.tagLabel.text = tagData
self.tagMaxWidthConstraint.constant = maxWidth
}
}