-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
80010a1
commit ac6aa3f
Showing
2 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import SwiftUI | ||
|
||
/** | ||
|
||
*/ | ||
public struct SnapCarousel<Content: View, T: Identifiable>: View { | ||
var content: (T) -> Content | ||
var items: [T] | ||
|
||
// property | ||
var spacing: CGFloat | ||
var trailingSpace: CGFloat | ||
|
||
@Binding var index: Int | ||
|
||
public init( | ||
spacing: CGFloat = 16, | ||
trailingSpace: CGFloat = 100, | ||
index: Binding<Int>, | ||
items: [T], | ||
@ViewBuilder content: @escaping (T) -> Content | ||
) { | ||
self.spacing = spacing | ||
self.trailingSpace = trailingSpace | ||
self._index = index | ||
self.items = items | ||
self.content = content | ||
} | ||
|
||
@GestureState var offset: CGFloat = 0 | ||
@State var currentIndex: Int = 0 | ||
@State var isScroll: Bool = false | ||
|
||
public var body: some View { | ||
GeometryReader { proxy in | ||
let width = proxy.size.width - (trailingSpace - spacing) | ||
let adjustMentWidth = (trailingSpace / 2) - spacing | ||
|
||
HStack(spacing: spacing) { | ||
ForEach(items) { item in | ||
content(item) | ||
.frame(width: proxy.size.width - trailingSpace) | ||
} | ||
} | ||
.padding(.horizontal, spacing) | ||
.offset(x: (CGFloat(currentIndex) * -width) + (currentIndex != 0 ? adjustMentWidth : 0) + offset) | ||
.gesture( | ||
DragGesture() | ||
.updating($offset, body: { value, out, _ in | ||
out = value.translation.width | ||
}) | ||
.onEnded({ value in | ||
let offsetX = value.translation.width | ||
let progress = -offsetX / width | ||
let roundIndex = progress.rounded() | ||
|
||
currentIndex = max(min(currentIndex + Int(roundIndex), items.count - 1), 0) | ||
currentIndex = index | ||
isScroll = false | ||
}) | ||
.onChanged({ value in | ||
isScroll = true | ||
let offsetX = value.translation.width | ||
let progress = -offsetX / width | ||
let roundIndex = progress.rounded() | ||
|
||
index = max(min(currentIndex + Int(roundIndex), items.count - 1), 0) | ||
}) | ||
) | ||
} | ||
.onChange(of: index, perform: { value in | ||
if !isScroll { | ||
currentIndex = value | ||
} | ||
}) | ||
.animation(.easeInOut, value: offset == 0) | ||
.animation(.easeInOut, value: currentIndex) | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import SwiftUI | ||
|
||
public struct PageControllView: UIViewRepresentable { | ||
@Binding var currentPage: Int | ||
var numberOfPages: Int = 0 | ||
|
||
public init(currentPage: Binding<Int>, numberOfPages: Int) { | ||
self._currentPage = currentPage | ||
self.numberOfPages = numberOfPages | ||
} | ||
|
||
public func makeCoordinator() -> Coordinator { | ||
Coordinator(self) | ||
} | ||
|
||
public func makeUIView(context: Context) -> UIPageControl { | ||
let pageControl = UIPageControl() | ||
pageControl.currentPageIndicatorTintColor = .label | ||
pageControl.numberOfPages = numberOfPages | ||
pageControl.pageIndicatorTintColor = .secondaryLabel | ||
pageControl.addTarget( | ||
context.coordinator, | ||
action: #selector(Coordinator.updateCurrentPage(sender:)), | ||
for: .valueChanged | ||
) | ||
return pageControl | ||
} | ||
|
||
public func updateUIView(_ uiView: UIPageControl, context: Context) { | ||
uiView.currentPage = currentPage | ||
} | ||
|
||
public class Coordinator: NSObject { | ||
var pageControl: PageControllView | ||
|
||
init(_ pageControl: PageControllView) { | ||
self.pageControl = pageControl | ||
} | ||
|
||
@objc func updateCurrentPage(sender: UIPageControl) { | ||
pageControl.currentPage = sender.currentPage | ||
} | ||
} | ||
} |