SwiftUI 拖动手势应用于父视图

SwiftUI Drag gesture applies to parent view

我已经对 Foreach 视图内的图像视图应用了带有一些动作的拖动手势,但是当我拖动图像时 - 它在视觉上拖动了父视图内的所有图像,甚至在另一个带有图像的 Foreach 视图中。不过,应用于所选图像的操作可以正常工作。我怎样才能让选定的图像移动而所有其他图像保持静止?

手势变量:

@State var position = CGSize.zero
@GestureState private var dragOffset = CGSize.zero

有代码:

ScrollView(.horizontal) {
                HStack(alignment: .center, spacing: 0) {
                    ForEach ((0..<player.playersCards.count), id: \.self) {number in
                        VStack {
                            Image(player.playersCards[number].pic)
                                .resizable()
                                .modifier(CardStyle())
                                .offset(dragOffset)
                                .gesture(
                                    DragGesture()
                                        .updating($dragOffset, body: { (value, state, transaction) in

                                            state = value.translation
                                        })
                                        .onEnded({ (value) in
                                            self.position.height += value.translation.height
                                            self.position.width += value.translation.width

                                            //player's turn
                                            
                                        })
                                )
                                .animation(.spring())

                            Text("\(ai.getPower(card: player.playersCards[number]))")
                                .modifier(TextModifier())
                        }
                    }
                }
            }

您必须为 playersCards 定义 number 就像您为此定义 pic 一样,它必须从0开始到你的最后一张牌,然后用这个向下的代码拖动

ScrollView(.horizontal) {
                HStack(alignment: .center, spacing: 0) {
                    ForEach ((0..<player.playersCards.count), id: \.self) {number in
                        VStack {
                            Image(player.playersCards[number].pic)
                                .resizable()
                                .modifier(CardStyle())
                                .offset(dragOffset)
                                .gesture(
                                    DragGesture()
                                        .updating($dragOffset, body: { (value, state, transaction) in
    
                                            if player.playersCards[number].number == number {     // <<: Here
                                                state = value.translation
                                            }
                                           
                                        })
                                        .onEnded({ (value) in
                                            
                                            if player.playersCards[number].number == number {    // <<: Here
                                                
                                                self.position.height += value.translation.height
                                                self.position.width += value.translation.width
                                                
                                            }
                                            
       
    
                                            //player's turn
                                            
                                        })
                                )
                                .animation(.spring())
    
                            Text("\(ai.getPower(card: player.playersCards[number]))")
                                .modifier(TextModifier())
                        }
                    }
                }
            }

因为你forEach里面的所有图片都设置为单张@GestureState属性,所以拖一个的时候全部映射到它被拖到 body 刷新。您可以有单独的 array 将卡片的每个拖动状态唯一地存储在特定索引处。

struct LanguageView: View {


    @State var position = CGSize.zero
    @GestureState private var dragOffset:[CGSize]

    init() {
        let  dragOffsets = [CGSize](repeating: CGSize.zero, count: 5) // Initialise with your model array count
        _dragOffset = GestureState(wrappedValue: dragOffsets)
    }

    var body: some View {
        ScrollView(.horizontal) {
            HStack(alignment: .center, spacing: 5) {
                ForEach ((0..<5)) {number in
                    VStack {
                        Image("ABC")
                            .resizable()
                            .frame(width: 300, height: 100)
                            //.modifier(CardStyle())
                            .offset(dragOffset[number])
                            .gesture(
                                DragGesture()
                                    .updating($dragOffset, body: { (new, existing, transaction) in

                                        existing[number] = new.translation
                                    })
                                    .onEnded({ (value) in
                                        self.position.height += value.translation.height
                                        self.position.width += value.translation.width

                                        //player's turn

                                    })
                            )
                            .animation(.spring())

                        Text("Foo")
                        // .modifier(TextModifier())
                    }
                }
            }
        }.frame(width: 500, height: 100)
    }
}