Modify view inside a ForEach in SwiftUI

810 Views Asked by At

I tried to update the position of one item of a ForEach. I want to drag only one item out of the array in the ForEach. The rest should stay the same. I tried several different ways and the outcome was always that all items where dragged or no item at all.

I am really frustrated at this stage, so I would be more than happy, if you can help me! If you need further information feel free to ask, I am new here on stackOverflow.

struct ContentView: View {

    var texts: [String] = ["Test1", "Test2"]

    @State var positon: CGSize = .zero

    var body: some View {
        HStack {
            ForEach(texts, id: \.self) { text in
                Text(text)
                    .offset(y: positon.height)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                positon = value.translation
                            }
                            .onEnded { value in
                                positon = .zero
                            }
                    )
            }
        }
    }
}
2

There are 2 best solutions below

1
On BEST ANSWER

Both Text views are dragged at the same time, because both Text views offset(y: ...) depend on the same position variable.


Something like this should work:

struct ContentView: View {

    var texts: [String] = ["Test1", "Test2"]

    var body: some View {
        HStack {
            ForEach(texts, id: \.self) { text in
                DraggableText(text: text)
            }
        }
    }
}

struct DraggableText: View {

    var text: String

    @GestureState var position: CGSize = .zero

    var body: some View {
        Text(text)
            .offset(y: position.height)
            .gesture(
                DragGesture().updating($position, body: { value, state, transaction in
                    state = value.translation
                })
            )
    }
}

Each DraggableText has its own position property.

0
On

You are changing the value position which is used the same way for both views.

You will need a separate @State variable for each view if you want them to move independently, or some other way to keep track of their positions separately.