SwiftUI: How to implement paging on user swipe? (Previously used UICollectionView -> paging enabled)

Viewed 4662

Background: I'm converting a project from UIKit to SwiftUI. Currently with UIKit, I have a UICollectionView within a UICollectionView, both with Paging enabled. This allows users to swipe up/down and left/right on cells. Each cell fills the entire screen (similar to TikTok's main UI) and each cell has a lot of data to pull from Firebase, so I do not want to load all items when the first view appears, but rather as each cell will appear (this is the current implementation under UIKit via UICollectionView delegates).

Problem: I can't find a way to enable this "paging" (based on user swiping) in SwiftUI. It's hard to imagine that Apple made this new framework without a Paging feature? If they haven't included this, is there a workaround? Otherwise, is there an easy way to include a UICollectionView into a SwiftUIView?

Any help or workarounds would be nice! Thanks :)

2 Answers

SwiftUI 2

It looks like a LazyGrid may be what you need.

Here is a sample code for a vertical grid:

struct ContentView: View {
    let data = (1...1000).map { "Item \($0)" }

    let columns = [
        GridItem(.adaptive(minimum: 80))
    ]

    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 20) {
                ForEach(data, id: \.self) { item in
                    Text(item)
                }
            }
            .padding(.horizontal)
        }
    }
}

You can find more information in these links:


SwiftUI 1

If you're bound to iOS 13 or LazyGrid just doesn't match your expectations, you can still wrap your UICollectionView in UIViewRepresentable.

See this link for more explanation: Implementing UICollectionView / UICollectionView DiffableDataSource in SwiftUI

You can try to use scrollview for this feature with such custom modifier:

struct ScrollViewPagingModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .onAppear {
                UIScrollView.appearance().isPagingEnabled = true
            }
            .onDisappear {
                UIScrollView.appearance().isPagingEnabled = false
            }
    }
}

extension ScrollView {
    func isPagingEnabled() -> some View {
        modifier(ScrollViewPagingModifier())
    }
}
Related