Ben Myers
Ben Myers

Reputation: 1395

Gesture for "touch enters" in SwiftUI

I am displaying a series of looped views using a VStack. When the user taps down on one of these views, it is highlighted. In order to get the highlight to show on a touch down, and not when a touch is released, I used a DragGesture with a minimumDistance value of 0:

private func highlightGesture(_ i: Int) -> some Gesture {
  DragGesture(minimumDistance: 0.0)
    .onChanged { _ in highlight = i }
    .onEnded { _ in highlight = nil }
}

However, I want the highlight to update when the user's drag gesture enters another view. For instance, if I tap and highlight the first view, then move my finger over to the second view without taking it off the screen, it should highlight the second view.

With the gesture shown above, a view is only highlighted when it is tapped. Instead, I'd like the view to be highlighted when it is tapped or when touch enters the view.

Any help is greatly appreciated.

Upvotes: 1

Views: 464

Answers (1)

here is a simple example that shows a possible way to drag your finger across 2 views/images and highlight them when it enters the different views/images. You will have to do a lot more work with this. Hope it helps.

struct ContentView: View {

class ImgObj: ObservableObject {
    @Published var img1Rec: CGRect = CGRect.zero
    @Published var img2Rec: CGRect = CGRect.zero
    @Published var img1Color: Color = .black
    @Published var img2Color: Color = .black
}

@ObservedObject var imgObj = ImgObj()
@GestureState var dragVar = CGSize.zero

var body: some View {
    
    let dragger = DragGesture(minimumDistance: 0.0, coordinateSpace: .global)
        .updating($dragVar, body: { (value, _, _) in
            imgObj.img1Color = imgObj.img1Rec.contains(value.location) ? .red : .black
            imgObj.img2Color = imgObj.img2Rec.contains(value.location) ? .red : .black
        })
    
    GeometryReader { geometry in
        VStack {
            Image(systemName: "clock").resizable().frame(width: 222, height: 222)
                .foregroundColor(imgObj.img1Color)
                .gesture(dragger)
                .onAppear {
                    // use geometry.frame(in: .global) somehow to get the CGRect
                    imgObj.img1Rec = CGRect(x: 0, y: 0, width: 222, height: 222)
                }
            Image(systemName: "folder").resizable().frame(width: 222, height: 222)
                .foregroundColor(imgObj.img2Color)
                .gesture(dragger)
                .onAppear {
                    // use geometry.frame(in: .global) somehow to get the CGRect
                    imgObj.img2Rec = CGRect(x: 0, y: 222, width: 222, height: 222)
                }
        }
    }
}
}

Edit note:

instead of:

            .onAppear {
                // use geometry.frame(in: .global) somehow to get the CGRect
                imgObj.img1Rec = CGRect(x: 0, y: 222, width: 222, height: 222)
            }
            

you could use:

                 .background(
                    GeometryReader { proxy in
                        Color.clear
                            .onAppear {
                                imgObj.img1Rec = proxy.frame(in: .global)
                            }
                    })
                    

Upvotes: 1

Related Questions