infinite loop carousel

pull/874/head
ryanzhao 2 years ago
parent b4d414bbfe
commit c2f57700a5

@ -54,7 +54,7 @@ struct MessageInfoView: View {
} }
// TODO: Attachment carousel view // TODO: Attachment carousel view
SessionCarouselView_SwiftUI(colors: [.orange, .gray, .blue, .yellow]) SessionCarouselView_SwiftUI(contentInfos: [.orange, .gray, .blue, .yellow])
.frame( .frame(
maxWidth: .infinity, maxWidth: .infinity,
maxHeight: .infinity, maxHeight: .infinity,

@ -3,36 +3,44 @@
import SwiftUI import SwiftUI
public struct SessionCarouselView_SwiftUI: View { public struct SessionCarouselView_SwiftUI: View {
@State var index = 0 @State var index = 1
var colors: [Color] var contentInfos: [Color]
let numberOfPages: Int
public init(colors: [Color]) { public init(contentInfos: [Color]) {
self.colors = colors self.contentInfos = contentInfos
self.numberOfPages = contentInfos.count
let first = self.contentInfos.first!
let last = self.contentInfos.last!
self.contentInfos.append(first)
self.contentInfos.insert(last, at: 0)
} }
public var body: some View { public var body: some View {
HStack(spacing: 0) { HStack(spacing: 0) {
ArrowView(value: $index.animation(.easeInOut), range: 0...(colors.count - 1), type: .decrement) ArrowView(index: $index, numberOfPages: numberOfPages, type: .decrement)
.zIndex(1) .zIndex(1)
PageView(index: $index.animation(), maxIndex: colors.count - 1) { PageView(index: $index, numberOfPages: self.numberOfPages) {
ForEach(self.colors, id: \.self) { color in ForEach(self.contentInfos, id: \.self) { color in
Rectangle() Rectangle()
.foregroundColor(color) .foregroundColor(color)
} }
} }
.aspectRatio(1, contentMode: .fit) .aspectRatio(1, contentMode: .fit)
ArrowView(value: $index.animation(.easeInOut), range: 0...(colors.count - 1), type: .increment) ArrowView(index: $index, numberOfPages: numberOfPages, type: .increment)
.zIndex(1) .zIndex(1)
} }
} }
} }
struct ArrowView: View { struct ArrowView: View {
@Binding var value: Int @Binding var index: Int
let range: ClosedRange<Int> let numberOfPages: Int
let maxIndex: Int
let type: ArrowType let type: ArrowType
enum ArrowType { enum ArrowType {
@ -40,9 +48,10 @@ struct ArrowView: View {
case decrement case decrement
} }
init(value: Binding<Int>, range: ClosedRange<Int>, type: ArrowType) { init(index: Binding<Int>, numberOfPages: Int, type: ArrowType) {
self._value = value self._index = index
self.range = range self.numberOfPages = numberOfPages
self.maxIndex = numberOfPages + 1
self.type = type self.type = type
} }
@ -63,36 +72,40 @@ struct ArrowView: View {
} }
func decrement() { func decrement() {
if value > range.lowerBound { withAnimation(.easeOut) {
value -= 1 self.index -= 1
} }
if value < range.lowerBound {
value = range.lowerBound if self.index == 0 {
self.index = self.maxIndex - 1
} }
} }
func increment() { func increment() {
if value < range.upperBound { withAnimation(.easeOut) {
value += 1 self.index += 1
} }
if value > range.upperBound {
value = range.upperBound if self.index == self.maxIndex {
self.index = 1
} }
} }
} }
struct PageView<Content>: View where Content: View { struct PageView<Content>: View where Content: View {
@Binding var index: Int @Binding var index: Int
let numberOfPages: Int
let maxIndex: Int let maxIndex: Int
let content: () -> Content let content: () -> Content
@State private var offset = CGFloat.zero @State private var offset = CGFloat.zero
@State private var dragging = false @State private var dragging = false
init(index: Binding<Int>, maxIndex: Int, @ViewBuilder content: @escaping () -> Content) { init(index: Binding<Int>, numberOfPages: Int, @ViewBuilder content: @escaping () -> Content) {
self._index = index self._index = index
self.maxIndex = maxIndex self.numberOfPages = numberOfPages
self.content = content self.content = content
self.maxIndex = numberOfPages + 1
} }
var body: some View { var body: some View {
@ -120,12 +133,17 @@ struct PageView<Content>: View where Content: View {
withAnimation(.easeOut) { withAnimation(.easeOut) {
self.dragging = false self.dragging = false
} }
switch self.index {
case 0: self.index = self.maxIndex - 1
case self.maxIndex: self.index = 1
default: break
}
} }
) )
} }
.clipped() .clipped()
PageControl(index: $index, maxIndex: maxIndex) PageControl(index: $index, maxIndex: numberOfPages - 1)
.padding(EdgeInsets(top: 0, leading: 0, bottom: 8, trailing: 0)) .padding(EdgeInsets(top: 0, leading: 0, bottom: 8, trailing: 0))
} }
} }
@ -157,7 +175,7 @@ struct PageControl: View {
HStack(spacing: 4) { HStack(spacing: 4) {
ForEach(0...maxIndex, id: \.self) { index in ForEach(0...maxIndex, id: \.self) { index in
Circle() Circle()
.fill(index == self.index ? Color.white : Color.gray) .fill(index == ((self.index - 1) % (self.maxIndex + 1)) ? Color.white : Color.gray)
.frame(width: 6.62, height: 6.62) .frame(width: 6.62, height: 6.62)
} }
} }
@ -180,7 +198,7 @@ struct SessionCarouselView_SwiftUI_Previews: PreviewProvider {
Color.black Color.black
} }
SessionCarouselView_SwiftUI(colors: [.red, .orange, .blue]) SessionCarouselView_SwiftUI(contentInfos: [.red, .orange, .blue])
} }
} }
} }

Loading…
Cancel
Save