Aod*_*odh 5 ios uicollectionview uicollectionviewcompositionallayout
我正在使用 UICollectionViewCompositionalLayout 在我的 iOS 应用程序中创建水平滚动(正交滚动)列表的垂直滚动列表。
当我为项目和组指定估计高度时,当较高的项目滚动到视图中时,集合视图会调整其高度。
另一方面,如果我指定组的估计高度和项目的小数高度 1.0,则无论设置的约束和压缩阻力如何,高度似乎都会被视为绝对值。
这是我的 createSection 函数:
func createSection(sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .absolute(90),
heightDimension: .estimated(44)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(90 / layoutEnvironment.container.effectiveContentSize.width),
heightDimension: .estimated(44)
)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 16.0
section.orthogonalScrollingBehavior = .continuous
return section
}
Run Code Online (Sandbox Code Playgroud)
我尝试进行子类化UICollectionViewCompositionalLayout和重写,layoutAttributesForElementsInRect以根据每个部分中最高的项目来调整属性。然而,这导致滚动期间闪烁,我怀疑这是由于prepare在边界变化时被连续调用所致。
我事先不知道每个单元格中视图的高度。但是,我已确保它们受到正确约束,并且垂直轴上的压缩阻力设置为所需的值。
预期行为:每个单元格的高度根据其内容动态调整,当不同高度的单元格进入视图时,不会导致布局变化或闪烁。
实际行为:为项目和组指定估计高度会导致滚动时布局发生变化,而为项目设置分数高度会导致组的估计高度被视为绝对值。重写layoutAttributesForElementsInRect并在那里调整会导致闪烁。
如何处理 UICollectionViewCompositionalLayout 中的动态单元格高度而不导致这些布局问题?我将非常感谢任何建议或潜在的解决方案。
这是一个演示该问题的 Swift Playground:https://github.com/aodhol/CompositionalProblem/tree/main
显示估计尺寸太大和太小的屏幕截图:
在 iOS 世界中,UICollectionViewCompositionalLayout 的设计并不是为了在向组方向滚动时处理不同大小的单元格。设置正交滚动行为后,通常认为正交滚动组中的所有项目都具有相同的大小。
但别担心,我们有一个解决方法。我们可以将 UICollectionViewFlowLayout 用于内部列表,而不是对外部垂直列表和内部水平列表使用 UICollectionViewCompositionalLayout。这种方法非常灵活,可以处理可变的单元尺寸。但是,请记住,如果您有大量数据,这可能不是最高效的解决方案。
让我们像这样重构你的 createSection 函数:
func createSection(sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(44)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(44)
)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 1)
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 16.0
return section
}
Run Code Online (Sandbox Code Playgroud)
然后,在处理您的 时UICollectionViewDataSource,您将像往常一样出列并设置您的单元。但这里有一个转折点 - 在每个单元格内,您将UICollectionView使用 a 进行嵌套UICollectionViewFlowLayout:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCell.identifier, for: indexPath) as! MyCell
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.estimatedItemSize = CGSize(width: 90, height: 44)
cell.nestedCollectionView.collectionViewLayout = flowLayout
cell.nestedCollectionView.dataSource = self
cell.nestedCollectionView.delegate = self
cell.nestedCollectionView.reloadData()
return cell
}
Run Code Online (Sandbox Code Playgroud)
最后,确保您的单元格可以处理嵌套UICollectionView:
class MyCell: UICollectionViewCell {
static let identifier = "MyCell"
let nestedCollectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(nestedCollectionView)
NSLayoutConstraint.activate([
nestedCollectionView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
nestedCollectionView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
nestedCollectionView.topAnchor.constraint(equalTo: contentView.topAnchor),
nestedCollectionView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Run Code Online (Sandbox Code Playgroud)
该解决方案应该提供您正在寻找的行为,但请记住它需要管理两个集合视图。此外,您可能会遇到一些需要解决的其他挑战。如果你有大量的单元,这个解决方法可能会慢一点,所以不能随意使用它。
| 归档时间: |
|
| 查看次数: |
581 次 |
| 最近记录: |