I have a draggable text and I have a red rectangle . I am trying to have that draggable text within that red rectangle and to only allow it to be dragged inside that rectangle . I have this code so far and it does everything that I need except the restricting the draggable text part to be inside the red rectangle, any suggestions on how I can confine the draggable text to only be inside the red rectangle ?
struct DraginContainerView: View {
@State var viewState = CGSize.zero
var body: some View {
VStack {
Rectangle()
.fill(.red)
.frame(width: 200, height: 200)
Text("My Text")
.foregroundColor(.black)
.offset(x: viewState.width, y: viewState.height)
.gesture(
DragGesture()
.onChanged { value in
viewState = value.translation
}.onEnded { value in
self.viewState = value.translation
}
)
}
}
}
Change your VStack
to a ZStack
so the text is on top of your Rectangle()
We have to get the width and height of the text. This is not easy, but we we can achieve this by applying a GeometryReader
to a clear text background.
The last thing is to check if our translation from the DragGesture
is in your predefined width and height of the Rectangle()
.
struct DraginContainerView: View {
@State var viewState = CGVector(dx: 0, dy: 0)
@State var textProxy = CGSize.zero
let width: CGFloat = 200
let height: CGFloat = 200
var body: some View {
ZStack {
Rectangle()
.fill(.red)
.frame(width: width, height: height)
Text("My Text")
.foregroundColor(.black)
.offset(x: viewState.dx, y: viewState.dy)
.gesture(
DragGesture()
.onChanged { value in
if value.translation.width < (width/2 - textProxy.width/2) && value.translation.width + (width/2 - textProxy.width/2) > 0 {
viewState.dx = value.translation.width
}
if value.translation.height < (height/2 - textProxy.height/2) && value.translation.height + (height/2 - textProxy.height/2) > 0 {
viewState.dy = value.translation.height
}
}.onEnded { value in
self.viewState = CGVector(dx: 0, dy: 0)
}
)
.background {
GeometryReader { proxy in
Color.clear
.onAppear {
textProxy = proxy.size
}
}
}
}
}
}