paging stack view

성민·2023년 7월 3일
0

swift

목록 보기
1/6


import SwiftUI

struct PagingCollectionUI<T: Hashable, Content: View>: View {
    
    @State private var currentIndex: Int = 0
    @State private var offset: CGFloat = 0
    @State private var startOffset: CGFloat = 0
    
    @Binding var items: [T]
    
    var height: CGFloat = 100
    var padding: CGFloat = 20.0
    var spacing: CGFloat = 10.0
    
    let contentView: (T) -> Content
    
    var body: some View {
        VStack {
            GeometryReader { geometry in
                let cellWidth = geometry.size.width - (padding * 2)
                
                ScrollView(.horizontal, showsIndicators: true) {
                    LazyHStack(spacing: spacing) {
                        ForEach(items, id: \.self) { index in
                            contentView(index)
                            .frame(width: cellWidth, height: height)
                        }
                    }
                    .padding(.horizontal, padding)
                }
                .content.offset(x: offset)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            offset = startOffset + value.translation.width
                        }
                        .onEnded { value in
                            
                            var newIndex = currentIndex
                            let moveWidth = value.predictedEndTranslation.width
                            
                            if  newIndex < items.count - 1, moveWidth < -(cellWidth / 2) {
                                print("right")
                                newIndex += 1
                            } else if newIndex > 0, moveWidth > cellWidth / 2 {
                                print("left")
                                newIndex -= 1
                            }
                            
                            let targetOffset = CGFloat(newIndex) * (cellWidth + spacing)
                            
                            withAnimation(.easeOut) {
                                currentIndex = newIndex
                                offset = -targetOffset
                                startOffset = offset
                            }
                            
                        }
                )
            }
        }
        .clipped()
    }
}

extension Array {
    func randomElements(count: Int) -> [Element] {
        var elements = self
        var result: [Element] = []
        
        for _ in 0..<count {
            guard !elements.isEmpty else { break }
            let randomIndex = Int.random(in: 0..<elements.count)
            result.append(elements[randomIndex])
            elements.remove(at: randomIndex)
        }
        
        return result
    }
}

struct PagingCollectionUI_Container: View {
    
    @State var items1 = Array(0...10)
    @State var items2 = Array(0...10)
//    Array(1...100).randomElements(count: 10)
    
    @State var lastValue = 0
    
    var body: some View {
        ScrollView {
            VStack(alignment: .center) {
                PagingCollectionUI(items: $items1) { index in
                    Text("Item \(index)")
                        .frame(maxWidth: .infinity)
                        .frame(maxHeight: .infinity)
                        .background(.blue)
                }
                .frame(height: 200)
                .background(.gray)
                
                PagingCollectionUI(items: $items2, height: 300, padding: 50, spacing: 40) { index in
                    Text("Item \(index)")
                        .frame(maxWidth: .infinity)
                        .frame(maxHeight: .infinity)
                        .background(.white)
                }
                .frame(height: 400)
                .background(.gray)
                
                HStack {
                    PagingCollectionUI(items: $items2, height: 150) { index in
                        VStack {
                            Text("Item \(index)")
                                .frame(maxWidth: .infinity)
                                .frame(maxHeight: .infinity)
                                .background(.red)
                        }
                        .cornerRadius(10)
                    }
                    .frame(width: 200, height: 200)
                    .background(.gray)
                    
                    PagingCollectionUI(items: $items2, height: 150) { index in
                        VStack {
                            Text("Item \(index)")
                                .frame(maxWidth: .infinity)
                                .frame(maxHeight: .infinity)
                                .background(.red)
                        }
                        .cornerRadius(10)
                    }
                    .frame(width: 200, height: 200)
                    .background(.gray)
                }
            }
        }
    }
}

struct PagingCollectionUI_Previews: PreviewProvider {
    static var previews: some View {
        PagingCollectionUI_Container()
    }
}

0개의 댓글