UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SwiftUI: DragGesture Issue Between Parent and Child Views in SwiftUI

Forums > SwiftUI

I built the following view and wanted to implement the functionalities below:

When dragging in a blank space within GestureTestView, a MyCircle() will be added to the view. When dragging an existing MyCircle(), it should change the position of MyCircle() instead of adding a new view to GestureTestView. However, my code does not achieve the second functionality: when I drag an already added MyCircle(), its position does not change. Instead, a new MyCircle() is added to GestureTestView.

How can I solve this problem?

struct MyCircle: View {
    @Binding var position: CGPoint

    var moveGesture: some Gesture {
        DragGesture()
            .onChanged { value in
                position = value.location
            }
    }

    var body: some View {
        Circle()
            .fill(.blue)
            .position(position)
            .frame(width: 20)
            .gesture(moveGesture)
    }
}
struct GestureTestView: View {
    @State var points = [CGPoint]()
    @State var currentPosition = CGPoint(x: -100, y: -100)//CGPoint(x: -50, y: -50)

    var DrawGesture: some Gesture {
        DragGesture(minimumDistance: 0)
            .onChanged { value in
                currentPosition = value.location
            }
            .onEnded{ value in
                points.append(currentPosition)
            }
    }

    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                ForEach(points.indices, id: \.self) { index in
                    MyCircle(position: $points[index])
                }
                Circle()
                    .fill(.blue)
                    .position(currentPosition)
                    .frame(width: 20)
                Path { _ in
                }
                .stroke(.green, lineWidth: 8)
                .contentShape(Rectangle())

            }
            .gesture(DrawGesture)
            .frame(width: geometry.size.width, height: geometry.size.height)
            .background(.black)

        }
    }
}

.gif

1      

@Heyya's circle is a real drag....

However, my code does not achieve the second functionality:
when I drag an already added MyCircle(), its position does not change.
Instead, a new MyCircle() is added

Consider adding an array of circle objects to your TableView. As you tap into the TableView, grab the coordinates of the tap. Run through each circle object in the array to see if if there is a circle under the tap's coordinates. If it IS UNDER the tap coordinates, you can then update that circle's coordinates to match the user's finger drag.

If there's nothing under the tap gesture, this may tell your app to create a NEW circle object, and add it to the TableView's array of circles.

The Other Paul

Paul Hagerty is another excellent SwiftUI instructor who posts lessons on the YouTube. He is a professor at Standford University and teaches iOS programming to engineering students. Starting with Lesson 10, he creates an app titled "Emoji Art" designed for young children to add emoji (animals, birds, clowns, vehicles, etc) to a colorful background.

This app teaches dragging techniques, including drag-n-drop. I highly recommend you start with Lesson 10.

See-> Emoji Art

Keep Coding

1      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.