Skip to content

Instantly share code, notes, and snippets.

@mattThousand
Created November 30, 2019 17:08
Show Gist options
  • Save mattThousand/794a3d2d57242188211346f0f3411bc2 to your computer and use it in GitHub Desktop.
Save mattThousand/794a3d2d57242188211346f0f3411bc2 to your computer and use it in GitHub Desktop.
import SwiftUI
struct PaginatedView<Page: View & Identifiable>: View {
@State private var totalOffset: CGFloat = 0
@State private var pageOffset: CGFloat = 0
@State private var currentPageIndex: Int = 0
var pages: [Page]
var spacing: CGFloat
var body: some View {
GeometryReader { proxy in
VStack {
HStack(spacing: self.spacing) {
ForEach(self.pages) { (page: Page) in
page
.frame(width: proxy.size.width - self.spacing, height: proxy.size.height)
.shadow(radius: 5)
}
}
.padding(.bottom, 30)
.gesture(self.dragGesture(pageWidth: proxy.size.width))
.offset(x: self.totalOffset, y: 0)
DotsComponent(pageIndex: self.currentPageIndex,
pageCount: self.pages.count)
}
.onAppear {
self.totalOffset = proxy.size.width / 2 * (CGFloat(self.pages.count) - 1)
self.pageOffset = self.totalOffset
}
}
}
func dragGesture(pageWidth: CGFloat) -> AnyGesture<DragGesture.Value> {
let gesture = DragGesture()
.onChanged({ value in
self.totalOffset += value.translation.width
})
.onEnded({ value in
withAnimation {
if self.pageOffset != pageWidth * round(self.totalOffset / pageWidth) {
let o = self.pageOffset - self.totalOffset
print(self.pageOffset)
switch o {
case (-.infinity)...0:
guard self.currentPageIndex > 0 else {
self.totalOffset = self.pageOffset
return
}
// Decrement Index
self.currentPageIndex -= 1
case 0...(.infinity):
guard self.currentPageIndex < self.pages.count - 1 else {
self.totalOffset = self.pageOffset
return
}
// Increment Index
self.currentPageIndex += 1
default:
break
}
}
self.totalOffset = pageWidth * round(self.totalOffset / pageWidth)
self.pageOffset = self.totalOffset
}
})
return AnyGesture(gesture)
}
}
/// Page Model
struct Page: View, Identifiable {
var id: Int {
index
}
var index: Int
var body: some View {
Color.white
}
}
/// Paging Dots
private struct DotsComponent: View {
var pageIndex: Int
var pageCount: Int
var body: some View {
HStack(spacing: 10) {
ForEach(0..<self.pageCount) { index in
Circle()
.frame(width: 10, height: 10)
.foregroundColor(index == self.pageIndex ? .black : .gray)
}
}
}
}
/// Int to Float Conversion
private extension Int {
var toFloat: CGFloat {
CGFloat(self)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment