我在这里创建了一个演示项目来展示我的问题。我使用UiCollectionView
与UICollectionViewCompositionalLayout
和DiffiableDatasource
。我一共有4节,简单命名为Section1、Section2&、Section3和Section4。当视图加载时,我只显示前3个部分,而不显示第4部分。我想要的是,当我点击第1节中的任何项目时,我只想将其布局更改为列表类型。因此,我决定创建另一个第4节,我认为如果我点击第1节项目,我将删除所有项目,只添加第4节,它也显示了与第1节相同的项目,但在列表中。我是这么做的。我将张贴整个代码,因为它不是那么多,将更容易理解我是如何创建部分和添加数据到他们:
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
enum Section: String, CaseIterable {
case section1 = "Squares"
case section2 = "Big Rectangle"
case section3 = "Rectangles"
case section4 = "List"
}
enum SectionItem: Hashable {
case itemType1(Item1)
case itemType2
case itemType3(Item2)
}
private var dataSource: UICollectionViewDiffableDataSource<Section, SectionItem>!
var itemType1Array = [Item1(text: "1"), Item1(text: "2"), Item1(text: "3"), Item1(text: "4"), Item1(text: "5")]
var itemType2Array = [Item2(text: "6"), Item2(text: "7"), Item2(text: "8")]
var isShowingList = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
configureCollectionView()
configureDatasource()
generateInitialData(animated: true)
}
// MARK: - Setup CollectionView
private func configureCollectionView() {
collectionView.register(SimpleCollectionViewCell.self, forCellWithReuseIdentifier: SimpleCollectionViewCell.reuseIdentifer)
collectionView.collectionViewLayout = generateLayout()
collectionView.delegate = self
}
private func generateLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int,
layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let sectionLayoutKind = Section.allCases[sectionIndex]
switch sectionLayoutKind {
case .section1:
return self.generateSquareLayout()
case .section2:
return self.generateBigRectangleLayout()
case .section3:
return self.generateRectanglesLayout()
case .section4:
return self.generateListLayout()
}
}
return layout
}
private func generateSquareLayout() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1/3),
heightDimension: .fractionalWidth(1/3))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
return section
}
private func generateBigRectangleLayout() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalWidth(2/3))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
return section
}
private func generateRectanglesLayout() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(2/3),
heightDimension: .fractionalWidth(1/3))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
return section
}
private func generateListLayout() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(44))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 1, leading: 1, bottom: 1, trailing: 1)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(44))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
return section
}
// MARK: - Datasource
private func configureDatasource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView, cellProvider: { [unowned self] collectionView, indexPath, item in
return self.cell(collectionView: collectionView, indexPath: indexPath, item: item)
})
}
// MARK: Cell
private func cell(collectionView: UICollectionView, indexPath: IndexPath, item: SectionItem) -> UICollectionViewCell {
switch item {
case .itemType1(let item1):
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SimpleCollectionViewCell.reuseIdentifer, for: indexPath) as? SimpleCollectionViewCell else { fatalError("Could not create new cell") }
cell.configure(item1.text)
return cell
case .itemType2:
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SimpleCollectionViewCell.reuseIdentifer, for: indexPath) as? SimpleCollectionViewCell else { fatalError("Could not create new cell") }
cell.configure("Mid")
return cell
case .itemType3(let item2):
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SimpleCollectionViewCell.reuseIdentifer, for: indexPath) as? SimpleCollectionViewCell else { fatalError("Could not create new cell") }
cell.configure(item2.text)
return cell
}
}
private func generateInitialData(animated: Bool) {
var snapshot = NSDiffableDataSourceSnapshot<Section, SectionItem>()
switch isShowingList {
case true:
snapshot.appendSections([.section4])
snapshot.appendItems(itemType1Array.map { ViewController.SectionItem.itemType1($0) }, toSection: .section4)
case false:
snapshot.appendSections([.section1, .section2, .section3])
snapshot.appendItems(itemType1Array.map { ViewController.SectionItem.itemType1($0) }, toSection: .section1)
snapshot.appendItems([ViewController.SectionItem.itemType2], toSection: .section2)
snapshot.appendItems(itemType2Array.map { ViewController.SectionItem.itemType3($0) }, toSection: .section3)
}
dataSource.apply(snapshot, animatingDifferences: animated)
}
}
// MARK: - UICollectionView Delegate
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
guard let selectedItem = dataSource.itemIdentifier(for: indexPath) else { return }
switch selectedItem {
case .itemType1(_):
var oldSnapshot = dataSource.snapshot()
switch isShowingList {
case true:
oldSnapshot.deleteAllItems()
oldSnapshot.appendSections([.section1, .section2, .section3])
oldSnapshot.appendItems(itemType1Array.map { ViewController.SectionItem.itemType1($0) }, toSection: .section1)
oldSnapshot.appendItems([ViewController.SectionItem.itemType2], toSection: .section2)
oldSnapshot.appendItems(itemType2Array.map { ViewController.SectionItem.itemType3($0) }, toSection: .section3)
case false:
oldSnapshot.deleteAllItems()
oldSnapshot.appendSections([.section4])
oldSnapshot.appendItems(itemType1Array.map { ViewController.SectionItem.itemType1($0) }, toSection: .section4)
}
isShowingList = !isShowingList
DispatchQueue.main.async {
self.dataSource.apply(oldSnapshot, animatingDifferences: true)
}
case .itemType2:
print("section 2")
case .itemType3(_):
print("section 3")
}
}
}
开始时,它是这样看的:
但是当我点击任何单元格时,我希望它使用我创建的self.generateListLayout()
方法显示一个列表,但我只看到这个:
它显示了第1节的布局。在我的主应用程序中,我甚至使用了不同的单元格,并在模型中使用了一些虚拟对象,我使其可清洗,即使这样,单元格也在更新,即使我改变了项目的数量,它也在反映,但布局仍然与第1节相同。我期望使用hashables,它会强制更改布局,但它只更新了数据源,使用了不同的单元格和项目,但布局相同。我想在两个部分中使用相同的数组或项目。有没有其他方法可以达到我的目的?我只想显示10个项目最大在第一节和轻敲任何一个,显示在该阵列中的所有项目,并更改布局列表,还删除其他2节。
1条答案
按热度按时间dzjeubhm1#
所以我只是修改了数据而不是实际的布局。所以我修改了我的方法,告诉collectionView应用新的布局,如下所示: