【问题标题】:Slide Carousel cards on Cards tap in SwiftUI在 SwiftUI 中点击卡片上的滑动轮播卡片
【发布时间】:2023-01-09 00:19:00
【问题描述】:

我在 SwiftUI 中创建了一个旋转木马卡片,它正在处理 DragGesture

我想在点击卡片时获得相同的体验,即在 .onTapGesture 上,无论卡片被点击,它都应该滑动到屏幕中心,如所附视频所示

我当前的代码 -

import SwiftUI

struct Item: Identifiable {
    var id: Int
    var title: String
    var color: Color
}

class Store: ObservableObject {
    @Published var items: [Item]
    
    let colors: [Color] = [.red, .orange, .blue, .teal, .mint, .green, .gray, .indigo, .black]
    
    // dummy data
    init() {
        items = []
        for i in 0...7 {
            let new = Item(id: i, title: "Item \(i)", color: colors[i])
            items.append(new)
        }
    }
}

struct ContentView: View {
    
    @StateObject var store = Store()
    @State private var snappedItem = 0.0
    @State private var draggingItem = 0.0
    @State var activeIndex: Int = 0
    
    var body: some View {
        
        ZStack {
            ForEach(store.items) { item in
                
                // article view
                ZStack {
                    RoundedRectangle(cornerRadius: 18)
                        .fill(item.color)
                    Text(item.title)
                        .padding()
                }
                .frame(width: 200, height: 200)
                
                .scaleEffect(1.0 - abs(distance(item.id)) * 0.2 )
                .opacity(1.0 - abs(distance(item.id)) * 0.3 )
                .offset(x: myXOffset(item.id), y: 0)
                .zIndex(1.0 - abs(distance(item.id)) * 0.1)
            }
        }
        .gesture(getDragGesture())
        .onTapGesture {
            //move card to centre
        }
    }
    
    private func getDragGesture() -> some Gesture {
        
        DragGesture()
            .onChanged { value in
                draggingItem = snappedItem + value.translation.width / 100
            }
            .onEnded { value in
                withAnimation {
                    draggingItem = snappedItem + value.predictedEndTranslation.width / 100
                    draggingItem = round(draggingItem).remainder(dividingBy: Double(store.items.count))
                    snappedItem = draggingItem
                    
                    //Get the active Item index
                    self.activeIndex = store.items.count + Int(draggingItem)
                    if self.activeIndex > store.items.count || Int(draggingItem) >= 0 {
                        self.activeIndex = Int(draggingItem)
                    }
                }
            }
    }
    
    func distance(_ item: Int) -> Double {
        return (draggingItem - Double(item)).remainder(dividingBy: Double(store.items.count))
    }
    
    func myXOffset(_ item: Int) -> Double {
        let angle = Double.pi * 2 / Double(store.items.count) * distance(item)
        return sin(angle) * 200
    }
}

【问题讨论】:

    标签: swift swiftui carousel ios16 swiftui-ontapgesture


    【解决方案1】:

    您需要将 .onTapGesture() 修饰符应用于 ForEach 内的单个项目,而不是围绕它。

    然后,你只需要处理不同的情况,将点击的项目与当前在前面的项目进行比较,并相应地更改draggingItem的值。

    这是视图主体中的代码:

    ZStack {
        ForEach(store.items) { item in
            
            // article view
            ZStack {
                RoundedRectangle(cornerRadius: 18)
                    .fill(item.color)
                Text(item.title)
                    .padding()
            }
            .frame(width: 200, height: 200)
            
            .scaleEffect(1.0 - abs(distance(item.id)) * 0.2 )
            .opacity(1.0 - abs(distance(item.id)) * 0.3 )
            .offset(x: myXOffset(item.id), y: 0)
            .zIndex(1.0 - abs(distance(item.id)) * 0.1)
            
            // Here is the modifier - on the item, not on the ForEach
            .onTapGesture {
                
                // withAnimation is necessary
                withAnimation {
                    
                    // Handle all possible cases, comparing the current item
                    // with the one tapped
                    if item.id == 0 {
                        draggingItem = 0
                    } else if item.id > Int(draggingItem) {
                        if draggingItem == 0 {
                            draggingItem = Double(item.id)
                        } else {
                            draggingItem += 1
                        }
                    } else {
                        draggingItem -= 1
                    }
                }
            }
        }
    }
    .gesture(getDragGesture())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-14
      • 2021-05-19
      • 2022-08-18
      • 2019-08-06
      • 2020-07-29
      • 1970-01-01
      • 2021-06-24
      相关资源
      最近更新 更多