Please check Majid’s tutorial on making a PagerView. This tutorial uses Majid’s code with some small changes. If you want to understand how to create the PagerView using @ViewBuilder visit swiftwithmajid.com
Code Snippet Changes
What I’m changing
- Adding dots to indicate the number of pages inside the view.
- Making the swipe gesture weaker.
Here is the the container that will hold all of our pages. For explanation, please visit Majid’s page. Adjust the WeakGesture variable’s value to your liking. Below I have it alternating between 100 and -100 depending on the swipe direction.
struct PagesContainer <Content : View> : View {
let contentCount: Int
@State var index: Int = 0
let content: Content
@GestureState private var translation: CGFloat = 0
init(contentCount: Int, @ViewBuilder content: () -> Content) {
self.contentCount = contentCount
self.content = content()
}
var body: some View {
GeometryReader { geometry in
VStack {
HStack (spacing: 0){
self.content
.frame(width: geometry.size.width)
}
.frame(width: geometry.size.width, alignment: .leading)
.offset(x: -CGFloat(self.index) * geometry.size.width)
.offset(x: self.translation)
.animation(.interactiveSpring())
.gesture(
DragGesture().updating(self.$translation) { value, state, _ in
state = value.translation.width
}.onEnded { value in
var weakGesture : CGFloat = 0
if value.translation.width < 0 {
weakGesture = -100
} else {
weakGesture = 100
}
let offset = (value.translation.width + weakGesture) / geometry.size.width
let newIndex = (CGFloat(self.index) - offset).rounded()
self.index = min(max(Int(newIndex), 0), self.contentCount - 1)
}
)
HStack {
ForEach(0..<self.contentCount) { num in
Circle().frame(width: 10, height: 10)
.foregroundColor(self.index == num ? .primary : Color.secondary.opacity(0.5))
}
}
}
}
}
}
You can use it inside your ContentView as below, Provide the PagesContainer the number of contents you have inside it then add the view elements.
struct ContentView: View {
var body: some View {
PagesContainer(contentCount: 4) {
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.green.opacity(0.3))
.padding()
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.yellow.opacity(0.3))
.padding()
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.red.opacity(0.3))
.padding()
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue.opacity(0.3))
.padding()
}
.frame(width: 300, height: 400)
}
}
