I have this code:
import SwiftUI
struct ContentView: View {
@State private var offset = CGSize.zero
var body: some View {
ZStack {
Color.red
HStack {
Group {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(Color.black)
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(Color.yellow)
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(Color.blue)
}
.font(.system(size: 40))
.padding(.horizontal, 10)
.padding(.vertical, 5)
}
.background(
RoundedRectangle(cornerSize: CGSize(width: 50,height: 50))
.fill(.white)
)
.offset(x: offset.width, y: offset.height)
.contentShape(Rectangle())
.gesture(
DragGesture()
.onChanged { gesture in
offset = gesture.translation
}
)
.padding()
}
}
}
#Preview {
ContentView()
}
Using this, you drag the stack inside the red rectangle, but after you drop it at the final destination you can drag it again. What am I missing?
I hope I understood the problem.
The drag gesture's translation property shows how much it moved from current position. So just setting it to offset causes it to snap back to (0, 0)
in the start. So we declare an anchor
variable to be our anchor point. After end of every drag gesture, we set the anchor to translation with the current value off anchor added together. If we only set it to translation it suffers the same problem. So we add the current anchor
value with translation to get our new anchor
. And yes its a bit complicated.
And your .offset()
property needs to be after .contentShape()
because it will not move the contentShape if you put it after it.
struct ContentView: View {
@State private var offset = CGSize.zero
@State private var anchor = CGSize.zero
var body: some View {
ZStack {
Color.red
HStack {
Group {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(Color.black)
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(Color.yellow)
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(Color.blue)
}
.font(.system(size: 40))
.padding(.horizontal, 10)
.padding(.vertical, 5)
}
.background(
RoundedRectangle(cornerSize: CGSize(width: 50,height: 50))
.fill(.white)
)
.contentShape(Rectangle())
.offset(offset)
.gesture(
DragGesture()
.onChanged { gesture in
offset.width = gesture.translation.width + anchor.width
offset.height = gesture.translation.height + anchor.height
}
.onEnded { value in
anchor.width += value.translation.width
anchor.height += value.translation.height
}
)
.padding()
}
}
}