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 gesture
s 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
How Does Appdelegate.Swift Replace Appdelegate.H and Appdelegate.M in Xcode 6.3
Operation Not Permitted When Executing 'Killall' with Swift
Swift 5 Coredata Predicate Using Uuid
Saving Highscores with Nsuserdefaults
Differences Generic Protocol Type Parameter VS Direct Protocol Type
How Have Multiple Init() with Swift
Explicitly Unwrapping Optional Nil Does Not Cause Crash
Comparing Two Enum Variables Regardless of Their Associated Values
How to Compare Result to .Succeed in Swift
Swift Codable with Different Array Types
Handling an Attribute of an Xml Element in Swift
Diffrence Between Function and Generic Function in Swift
Code Highlighting in Latex for Swift
Integrating Congnito User Pools with Amazon Cognito Identity
Firebase Access Keys in Queryorderby