Swiftui on MACos - Handle Single-Click and Double-Click at the Same Time

SwiftUI on macOS - handle single-click and double-click at the same time

Here is possible approach (tested with Xcode 11.2 / macOS 10.15)

struct MyView: View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(width: 200, height: 200)
.gesture(TapGesture(count: 2).onEnded {
print("double clicked")
})
.simultaneousGesture(TapGesture().onEnded {
print("single clicked")
})
}
}

Handle single click and double click while updating the view

You can use a custom click handler like this:

class TapState {

static var taps: [String: Date] = [:]

static func isDoubleTap<Content: View>(for view: Content) -> Bool {
let key = "\(view)"
let date = taps[key]
taps[key] = Date()
if let date = date, date.timeIntervalSince1970 >= Date().timeIntervalSince1970 - 0.4 {
return true
} else {
return false
}
}
}

extension View {

public func onTapGesture(firstTap: @escaping () -> Void, secondTap: @escaping () -> Void) -> some View {
onTapGesture(count: 1) {
if TapState.isDoubleTap(for: self) {
secondTap()
} else {
firstTap()
}
}
}
}

And implement it like this:

struct MyView: View {

@State var isSelected: Bool = false
@State var isShowingDetail: Bool = false

var body: some View {
Text("Text")
.background(isSelected ? Color.green : Color.blue)
.onTapGesture(firstTap: {
isSelected = true
}, secondTap: {
isShowingDetail = true
})
.sheet(isPresented: $isShowingDetail) {
Text("Detail")
}
}
}

Swift Package

I've also created a small package you can use: https://github.com/lukaswuerzburger/DoubleTap

SwiftUI - Respond to tap AND double tap with different actions

First one prevent second one to perform. So reverse the order of your code:

.onTapGesture(count: 2) {
print("Double Tap!")
}
.onTapGesture(count: 1) {
print("Single Tap!")
}

Update: Second solution

Since the above method reported not working in some situationis, you can try using gestures modifier instead:

.gesture(TapGesture(count: 2).onEnded {
print("double clicked")
})
.simultaneousGesture(TapGesture().onEnded {
print("single clicked")
})

Is it possible to suppress single-click events during a double-click?

Start a timer when you get WM_LBUTTONDOWN (or Qt equivalent). If you get WM_LBUTTONDBLCLK (or Qt equivalent) before the timer expires, cancel the timer and execute your double-click action. Otherwise, when the timer expires, execute your single-click event.

On Windows, you can get the double-click time using GetDoubleClickTime().

That's about the best you can do - you can't prevent the single click message being generated in the first place on either platform.

Catching double click in Cocoa OSX

The mouseDown: and mouseUp: methods take an NSEvent object as an argument with information about the clicks, including the clickCount.



Related Topics



Leave a reply



Submit