Created
November 30, 2019 17:08
-
-
Save mattThousand/794a3d2d57242188211346f0f3411bc2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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