|
import SwiftUI |
|
|
|
// PURE SwiftUI way with State tracking to prevent double events |
|
|
|
struct ContentView: View { |
|
@State private var ignoreTapEvent = false |
|
|
|
var body: some View { |
|
Button { |
|
guard !ignoreTapEvent else { |
|
ignoreTapEvent = false |
|
return |
|
} |
|
|
|
print("Tapped") |
|
} label: { |
|
Text("Tap me!") |
|
} |
|
.simultaneousGesture(LongPressGesture(minimumDuration: 1.0) |
|
.onEnded { didEnd in |
|
ignoreTapEvent = true |
|
print("Long pressed!") |
|
} |
|
) |
|
} |
|
} |
|
|
|
// UIKit-assisted way by wrapping UIButton and using UILongPressGestureRecognizer to have system properly handle concurrent button gestures |
|
|
|
struct ContentView: View { |
|
var body: some View { |
|
LongPressButton(useCircularShape: true, systemIconName: "list.bullet.clipboard.fill") { |
|
print("Tap") |
|
} onLongPress: { |
|
print("Long press") |
|
} |
|
} |
|
} |
|
|
|
struct LongPressButton: View { |
|
let useCircularShape: Bool |
|
let systemIconName: String |
|
let onTap: () -> Void |
|
let onLongPress: () -> Void |
|
|
|
var body: some View { |
|
_LongPressButton(useCircularShape: useCircularShape, systemIconName: systemIconName, onTap: onTap, onLongPress: onLongPress) |
|
.fixedSize() |
|
} |
|
} |
|
|
|
struct _LongPressButton: UIViewRepresentable { |
|
let useCircularShape: Bool |
|
let systemIconName: String |
|
let onTap: () -> Void |
|
let onLongPress: () -> Void |
|
|
|
func makeUIView(context: Context) -> some UIView { |
|
var config = UIButton.Configuration.borderless() |
|
config.image = UIImage(systemName: systemIconName) |
|
config.cornerStyle = useCircularShape ? .capsule : UIButton.Configuration.borderless().cornerStyle |
|
|
|
let button = UIButton(configuration: config, primaryAction: .init() { action in |
|
onTap() |
|
}) |
|
|
|
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.longPressed(gestureRecognizer:))) |
|
button.addGestureRecognizer(longPressGestureRecognizer) |
|
|
|
return button |
|
} |
|
|
|
func updateUIView(_ uiView: UIViewType, context: Context) {} |
|
|
|
func makeCoordinator() -> Coordinator { |
|
Coordinator(button: self) |
|
} |
|
|
|
class Coordinator: NSObject, UIGestureRecognizerDelegate { |
|
let button: _LongPressButton |
|
|
|
init(button: _LongPressButton) { |
|
self.button = button |
|
} |
|
|
|
@objc func longPressed(gestureRecognizer: UILongPressGestureRecognizer) { |
|
guard gestureRecognizer.state == .began else { return } |
|
button.onLongPress() |
|
} |
|
} |
|
} |
kewl 👍