Home > database >  How to detect a single mouse down event in SwiftUI on macOS
How to detect a single mouse down event in SwiftUI on macOS

Time:10-30

I want to detect ONE mouse down and ONE mouse up event on my view (a simple Rectangle). Here is the code I already made. Unfortunately I got a lot of 'mouse down' and 'mouse up' on the console. This not what I want. I want just one 'mouse down' when the mouse is pressed on my rectangle and one 'mouse up' when the mouse is released.

    
  
    var body: some View {
        Rectangle()
            .onAppear(perform: {
                NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown]) { event in
                        print ("mouse down")
                    
                   return event
                }
                NSEvent.addLocalMonitorForEvents(matching: [.leftMouseUp]) { event in
                    print ("mouse up")
                    
                    return event
                }
            })
            
     }

CodePudding user response:

I found the solution by using a View modifier


//
//  ContentView.swift
//  OnPressedOnRelease
//

import SwiftUI

struct ContentView: View {
    @State private var message: String = "Click on rectangle"
    var body: some View {
        VStack {
            Image(systemName: "magicmouse")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("\(message)")
        
            Rectangle()
                .modifier(PressActions(
                    onPress: {
                        // Do something on press...
                        message = "Mouse down"
                    },
                    onRelease: {
                        // Do something on release...
                        message = "Mouse up"
                    }
                ))
                
        }
        .padding()
        .frame(width: 200, height: 200)
    }
}

struct PressActions: ViewModifier {
    var onPress: () -> Void
    var onRelease: () -> Void
    func body(content: Content) -> some View {
        content
            .simultaneousGesture(
                DragGesture(minimumDistance: 0)
                    .onChanged({ _ in
                        onPress()
                    })
                    .onEnded({ _ in
                        onRelease()
                    })
            )
    }
}



struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

CodePudding user response:

I've recently worked with Gestures and a good solution is to do this :

struct ContentView: View {
    @State var dragGestureValue: DragGesture.Value?
    
    var body: some View {
        Rectangle()
            .gesture(pressActionsGesture())
            .padding()
    }
    
    private func pressActionsGesture() -> some Gesture {
        return DragGesture(minimumDistance: 0)
            .onChanged {
                // If nil, it means its the beginning of the DragGesture
                if dragGestureValue == nil {
                    print("Mouse Down")
                }
                
                // Gives DragGesture informations to our @State value
                dragGestureValue = $0
            }
            .onEnded { _ in
                print("Mouse Up")
                
                dragGestureValue = nil
            }
    }
}
  • Related