1

I have HStack with some images shown via ForEach view. Each image has DragGesture applied. I can drag an image all over the screen and the animation shown correctly. But when I put my HStack with images into the ScrollView when I drag an image (not scroll) the animation of gragging shown only within the ScrollView area. How can I make it show within the whole screen again? enter image description here

import SwiftUI

struct SwiftUIView: View {
    
    @State var position = CGSize.zero
    @GestureState var dragOffset: [CGSize]

        init() {
            let  dragOffsets = [CGSize](repeating: CGSize.zero, count: 36)
            _dragOffset = GestureState(wrappedValue: dragOffsets)
        }
    
    var body: some View {
        ScrollView(.horizontal) {
            HStack(alignment: .center, spacing: 0) {
                ForEach ((0..<player.playersCards.count), id: \.self) { number in
                    Image(player.playersCards[number].pic)
                        .resizable()
                        .frame(width: 93, height: 127)
                        .modifier(CardStyle())
                        .offset(dragOffset[number])

                    .gesture(
                        DragGesture(coordinateSpace: .global)
                            .updating($dragOffset, body: { (value, state, transaction) in

                                state[number] = value.translation

                            })
                    )
                    .animation(.spring())
                }
            }
        }.offset(x: 15, y: 0)
    }
}
Leo
  • 37
  • 6

1 Answers1

3

You just need to pack your image into another view (group or ZStack)! Set the height of this view to the height of the screen, then the image will move inside the parent view:

struct SwiftUIView: View {
    
    private let colors = [Color.blue, Color.yellow, Color.orange, Color.gray, Color.black, Color.green, Color.white]
    
    @State var position = CGSize.zero
    @GestureState var dragOffset: [CGSize]

        init() {
            let  dragOffsets = [CGSize](repeating: CGSize.zero, count: 36)
            _dragOffset = GestureState(wrappedValue: dragOffsets)
        }
    
    var body: some View {
        
        ScrollView(.horizontal) {
            HStack(alignment: .center, spacing: 0) {
                ForEach (Array(0...6), id: \.self) { number in
                    ZStack {
                        Text("\(number.description)")
                            .frame(width: 93, height: 127)
                            .background(colors[number])
                            .offset(dragOffset[number])
                        .gesture(
                            DragGesture(coordinateSpace: .global)
                                .updating($dragOffset, body: { (value, state, transaction) in
                                    state[number] = value.translation

                                })
                        )
                        .animation(.spring())
                    }
                    .frame(width: 93, height: UIScreen.main.bounds.height)
                }
            }
        }
        .background(Color.red)
    }
}

result

Sergei Volkov
  • 818
  • 8
  • 15
  • Wow! That seems to be working, but... then it's a problem to move the scrollview back to the bottom of the screen. Any ideas? – Leo Sep 29 '21 at 09:50
  • Resolved the issue with .offset(y: screenHeight / 2 - playersCardsHeight / 2) – Leo Sep 29 '21 at 11:57