Search code examples
imageswiftuiforeachoffsetdrag

Drag multiple images separately in swift


I have just started coding and this is my first project, and I want to drag couple images set on the screen separately and leave them where they are dragged. However currently I could manage dragging images separately but comes back in their original position... what should I change if I want to leave each images where they are dragged.

HStack {
    ForEach(stickers) { sticker in
        Image(sticker.name)
            .resizable()
            .frame(width: self.screenWidth*0.2, height: self.screenWidth*0.2)
            .offset(x: self.selectedSticker == sticker ? self.dragOffset.width : 0,
                    y: self.selectedSticker == sticker ? self.dragOffset.height : 0)
            .gesture(
                DragGesture()
                    .updating(self.$dragOffset, body: { (value, state, transaction) in
                        if nil == self.selectedSticker {
                            self.selectedSticker = sticker
                        }
                        state = value.translation
                        
                    }).onEnded { _ in self.selectedSticker = nil }
            )
    }
}        

Solution

  • It seems that once the sticker is no longer the selected.sticker, its offset returns to zero. You'd need to set a variable that saves the images' locations after they are updated.

    You could perhaps add another variable, offset, to Sticker:

    struct Sticker: ... {
        var offset = CGSize.zero
        ...
    }
    

    And then store the offset value for each sticker in sticker.offset in .onEnded:

    HStack {
        ForEach(stickers) { sticker in
            Image(sticker.name)
                .resizable()
                .frame(width: self.screenWidth*0.2, height: self.screenWidth*0.2)
                .offset(x: self.selectedSticker == sticker ? self.dragOffset.width : sticker.offset.width,
                        y: self.selectedSticker == sticker ? self.dragOffset.height : sticker.offset.height)
                .gesture(
                    DragGesture()
                        .updating(self.$dragOffset, body: { (value, state, transaction) in
                            if nil == self.selectedSticker {
                                self.selectedSticker = sticker
                            }
                            state = value.translation
                        })
                        .onEnded { _ in
                            sticker.offset = dragOffset
                            self.selectedSticker = nil
                        }
                )
        }
    }