I created an Image with Drag gesture, but when I convert it to a Button, full screen become the button, so when I click to anywhere in the screen, the Button will be action
struct OwlFly: View {
private var bround = UIScreen.main.bounds
@State var isShow = false
@State private var location = CGPoint(x: 60, y: 60)
@GestureState private var startLocation: CGPoint? = nil
var simpleDrag: some Gesture {
DragGesture()
.onChanged { value in
var newLocation = startLocation ?? location
newLocation.x += value.translation.width
newLocation.y += value.translation.height
self.location = newLocation
self.location = value.location
}
.onEnded{ value in
if(value.translation.width > bround.size.width/2) {
self.location.x = bround.size.width - 30
}
else {
self.location.x = 30
}
}
.updating($startLocation) { (value, startLocation, transaction) in
startLocation = startLocation ?? location
}
}
var body: some View {
Button(action: {
self.isShow.toggle()
if(isFly) {
self.location.x = bround.width/2
}
else {
self.location.x = 30
}
}) { // I convert the Image to a label of button
Image("simpleDrag")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50)
.animation(.easeInOut)
.position(location)
.gesture(simpleDrag)
}
}
}
That is my code
This is nice!
The .position
expands the view (and the button) to maximum size, that's why you can click everywhere.
The easiest workaround is not using a Button, but making the image itself tappable – see code below.
PS: You don't have to use @GestureState
if you manage the dragging by yourself with onChanged
and onEnded
– you did a double job. I commented out everything you don't need ;)
struct ContentView: View {
private var bround = UIScreen.main.bounds
@State var isShow = false
@State private var location = CGPoint(x: 60, y: 60)
// @GestureState private var startLocation: CGPoint? = nil
var simpleDrag: some Gesture {
DragGesture()
.onChanged { value in
// var newLocation = location
// newLocation.x += value.translation.width
// newLocation.y += value.translation.height
// self.location = newLocation
self.location = value.location
}
.onEnded{ value in
if(value.translation.width > bround.size.width/2) {
self.location.x = bround.size.width - 30
}
else {
self.location.x = 30
}
}
// .updating($startLocation) { (value, startLocation, transaction) in
// startLocation = startLocation ?? location
// }
}
var body: some View {
Image(systemName: "bubble.right.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50)
.animation(.easeInOut, value: location)
.position(location)
.gesture(simpleDrag)
.onTapGesture {
self.isShow.toggle()
if(isShow) {
self.location.x = bround.width/2
}
else {
self.location.x = 30
}
}
}
}