I want to make a list view which contents could be dragged for reordering and tapped for detail. But when I add the onTapGesture() action in the content view, the onMove() action stop working.
Example code:
import SwiftUI
struct TestTapAndMove: View {
@State private var users = ["Paul", "Taylor", "Adele"]
var body: some View {
List {
ForEach(users, id: \.self) { user in
VStack {
Text("user: \(user)").font(.headline)
Divider()
}.background(Color.gray)
// The TapGesture will result in onMove action not working.
.onTapGesture(perform: {
print("tap!")
})
}
.onMove(perform: move)
}
}
func move(from source: IndexSet, to destination: Int) {
print("onMove!")
users.move(fromOffsets: source, toOffset: destination)
}
}
Is there any solution that could make the tap and move action work together?
As workaround you can make some specific part of row clickable, like text in below example (or some added custom shape or plain button)
VStack {
Text("user: \(user)").font(.headline)
.onTapGesture(perform: {
print("tap!")
})
Divider()
}.background(Color.gray)
Alternate: you can add helper custom view as row overlay which would handle tap/mouseDown action for view (and does not break drug)
class TapHandlerView: NSView {
override func mouseDown(with event: NSEvent) {
super.mouseDown(with: event) // keep this to allow drug !!
print("tap")
}
}
struct TapHandler: NSViewRepresentable {
func makeNSView(context: Context) -> TapHandlerView {
TapHandlerView()
}
func updateNSView(_ nsView: TapHandlerView, context: Context) {
}
}
and use it
VStack {
Text("user: \(user)").font(.headline)
Divider()
}.background(Color.gray)
.overlay(TapHandler()) // << here !!
Tested with Xcode 12.0 / macOS 10.15.6