A buttery smooth, lazy loaded, panning, zooming, and gesture dismissible view pager view for SwiftUI.
The goal of this package is to expose a simple SwiftUI interface for a fluid and seamless content viewer. Unlike other pagers for SwiftUI - this is built on top of UIKit APIs exposing features not yet available in SwiftUI.
The above example is from dateit demonstrating the capabilities of this library. Note: the overlay is custom and can be added by putting LazyPager
inside a ZStack
.
The above example can be found in the example project.
Add Package
https://github.com/gh123man/LazyPager
Add Package
Or add the package to your Package.swift
if your project is a Swift package.
A simple image pager that displays images by name from your app assets.
@State var data = [ ... ]
var body: some View {
LazyPager(data: data) { element in
Image(element)
.resizable()
.aspectRatio(contentMode: .fit)
}
}
That's it!
@State var data = [ ... ]
@State var show = true
@State var opacity: CGFloat = 1 // Dismiss gesture background opacity
@State var index = 0
var body: some View {
Button("Open") {
show.toggle()
}
.fullScreenCover(isPresented: $show) {
// Provide any list of data and bind to an index
LazyPager(data: data, page: $index) { element in
// Supports any kind of view - not only images
Image(element)
.resizable()
.aspectRatio(contentMode: .fit)
}
// Make the content zoomable
.zoomable(min: 1, max: 5)
// Enable the swipe to dismiss gesture and background opacity control
.onDismiss(backgroundOpacity: $opacity) {
show = false
}
// Handle single tap gestures
.onTap {
print("tap")
}
// Get notified when to load more content
.shouldLoadMore {
data.append("foobar")
}
// Set the background color with the drag opacity control
.background(.black.opacity(opacity))
// A special included modifier to help make fullScreenCover transparent
.background(ClearFullScreenBackground())
// Works with safe areas or ignored safe areas
.ignoresSafeArea()
}
}
@State var data = [ ... ]
var body: some View {
LazyPager(data: data, direction: .vertical) { element in
Image(element)
.resizable()
.aspectRatio(contentMode: .fill)
}
}
For a full working example, open the sample project in the examples folder, or check out the code here
.zoomable(min: CGFloat, max: CGFloat)
.shouldLoadMore
.ignoresSafeArea()
(or not) to get a true full screen view..onDismiss
- Supply a binding opacity value to control the background opacity during the transition. .onTap
to handle single taps (useful for hiding and showing UI).settings
to modify advanced settingsfullScreenCover
fullScreenCover
is a good native element for displaying a photo browser, however it has an opaque background by default that is difficult to remove. So LazyPager
provides a ClearFullScreenBackground
background view you can use to fix it. Simply add .background(ClearFullScreenBackground())
to the root element of your fullScreenCover
. This makes the pull to dismiss gesture seamless.
You can customize the double tap behavior using the zoomable(min: CGFloat, max: CGFloat, doubleTapGesture: DoubleTap)
. By default doubleTapGesture
is set to .scale(0.5)
which means "zoom 50% when double tapped". You can change this to a different ratio or set it to .disabled
to disable the double tap gesture.
By default .onDismiss
will be called after the pull to dismiss gesture is completed. It is often desirable to fade out the background in the process. LazyPager
uses a fully transparent background by default so you can set your own custom background. NOTE: .onDismiss
is only supported for .horizontal
pagers.
To control the dismiss opacity of a custom background, use a Binding<CGFloat>
like .onDismiss(backgroundOpacity: $opacity) {
to fade out your custom background.