A simple utility to assist with loading more content in a ScrollView
in SwiftUI.
Add .shouldLoadMore
to any ScrollView
. By default it will be triggered when the content at the bottom of the ScrollView
is close to being in view.
If you want to see it in a real app, check out dateit
Also works well with SwiftUI-Refresher
First add the package to your project.
import ScrollViewLoader
struct ContentView: View {
@State var data: [Int] = Array(0..<1)
var body: some View {
ScrollView {
LazyVStack {
ForEach(data, id: \.self) { i in
Text("\(i)")
.font(.title)
.frame(maxWidth: .infinity)
}
ProgressView()
.scaleEffect(2)
}
}
.shouldLoadMore {
await Task.sleep(seconds: 0.05)
data.append(data.last! + 1)
}
}
}
By default, the callback will be triggered when distance to the bottom of the scrollable content is less than 50%
of the visible hight of the scroll view. You can customize this
Set the relative offset to 20%
instead of the default 50%
:
.shouldLoadMore(bottomDistance: .relative(0.2)) {
// Load more
}
Set the absolute offset to a fixed value:
.shouldLoadMore(bottomDistance: .absolute(200)) {
// Load more
}
It may be desirable for shouldLoadMore
to be called whenever the user scrolls - even if the scroll view content didn't change. You can change this behavior with waitForHeightChange
:
.shouldLoadMore(waitForHeightChange: .never) {
// Will be called regardless of if the content height changed from a previous update
}
.shouldLoadMore(waitForHeightChange: .always) {
// Will only be called if the content height changed since last time
}
.shouldLoadMore(waitForHeightChange: .until(2)) {
// Will only be called if the content height changed since last time or after 2 seconds of no change
}
By default waitForHeightChange
is .until(2)
so the function doesn't get called in quick succession when no content updates are made.
- The callback will only be called once when the bottom approaches.
- If you scroll back up out of the trigger zone, it will be called again when you scroll back down.
- It is up to you to synchronize and de-duplicate multiple scroll triggers by the user (depending on the kind of data you are loading)
- Loading conditions will be re-evaluated if the scroll view content changes in any way.
.shouldLoadMore { done in
loadYourContent {
data.append(data.last! + 1)
done() // Call done so shouldLoadMore can be called again later
}
}
Larger batching