Skip to content

Commit

Permalink
feat: Add Onboarding Item
Browse files Browse the repository at this point in the history
  • Loading branch information
tsuzukihashi committed Jun 5, 2023
1 parent 80010a1 commit ac6aa3f
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
79 changes: 79 additions & 0 deletions Sources/TsuzuKit/Components/SnapCarousel.swift
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)
}
}
44 changes: 44 additions & 0 deletions Sources/TsuzuKit/Representable/PageControllView.swift
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
}
}
}

0 comments on commit ac6aa3f

Please sign in to comment.