User95797654974
User95797654974

Reputation: 644

Ignore top safe area for UICollectionViewCompositionalLayout.list

I am using compositional layout in a SwiftUI app.

I am using the list version of UICollectionViewCompositionalLayout and want the list to ignore the top safe area. I can't find any sources on how to do this.

Adding "collectionView.contentInsetAdjustmentBehavior = .never" messes up the scrolling for a second and crashes the app outright due to an error "recursive layout loop. This can happen when self-sizing views do not return consistent sizes, or the collection view's frame/bounds/contentOffset is being constantly adjusted"

I have added a minimal reproducible example below. You can literally copy and paste to see the issue.

struct ContentView: View {
    var body: some View {
        GeometryReader { geo in
            VCRepresentable()
        }
        .ignoresSafeArea(edges: .top)
    }
}

struct VCRepresentable: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        return LayoutVC()
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        
    }
}

struct Item: Hashable {
    let name: String
}

class LayoutVC: UIViewController {
    enum Section: CaseIterable {
        case main
    }
    
    let items = [Item(name: "Item 1"), Item(name: "Item 2"), Item(name: "Item 3")]
    var collectionView: UICollectionView!
    var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: createLayout())
        
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(collectionView)
        
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.topAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
        configureDataSource()
        applySnapshot()
    }
    
    func createLayout() -> UICollectionViewLayout {
        var listConfiguration = UICollectionLayoutListConfiguration(appearance: .grouped)
        listConfiguration.headerMode = .none
        listConfiguration.headerTopPadding = 0
        
        let layout = UICollectionViewCompositionalLayout.list(using: listConfiguration)
        return layout
    }

    func configureDataSource() {
        dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { [unowned self]collectionView, indexPath, item in
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
            if indexPath.row == 0 {
                cell.contentConfiguration = UIHostingConfiguration {
                    Color.blue
                        .frame(height: 100)

                }
                .margins(.all, 0)
            } else {
                cell.contentConfiguration = UIHostingConfiguration {
                    HStack {
                        Text("\(items[indexPath.row])")
                        
                        Spacer()
                    }
                    .frame(height: 44)
                }
            }
            return cell
        }
    }

    func applySnapshot() {
        var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
        snapshot.appendSections([.main])
         
        snapshot.appendItems(items)
        dataSource.apply(snapshot, animatingDifferences: false)
    }
}

What I basically want:

enter image description here

Upvotes: 0

Views: 67

Answers (0)

Related Questions