In SwiftUI on MacOS Detect Clicks and Doubleclicks in List

82 Views Asked by At

I have a List with a few lines.
The Lines contain two clickable Images and some text.

Clicking or Double-Clicking the Images shall trigger an action.
Clicking anywhere else in the Line shall select the Line in the List.
Double-Clicking anywhere else in the Line shall trigger an action.

The following code works in iOS, what's to be done, that it works in MacOS.

In MacOS (13.4.1 (c) (22F770820d)) I have the effect, that selection of lines with a single Click does not work properly.

struct Line_List: View {
  @State private var selectedRow: Int? = nil
  var body: some View {
    List(1..<11, id: \.self, selection: $selectedRow) { index in
      Line(index: index)
    }
  }
}

struct Line: View {
  var index: Int
  
  var body: some View {
    HStack (alignment: .top) {
      Image(systemName: "1.circle.fill")
        .onTapGesture (count: 2){
          print("Icon 1 Double-Clicked")
        }
        .onTapGesture (count: 1){
          print("Icon 1 Single-Clicked")
        }        
      VStack (alignment: .leading){
        Text("Line: \(index)")
        Text("Some other Text")
      }
      Spacer()
      Image(systemName: "2.circle.fill")
        .onTapGesture (count: 2){
          print("Icon2 Double-Clicked")
        }
        .onTapGesture (count: 1){
          print("Icon2 Single-Clicked")
        }
      
    }
    .background(Color.green)
    .onTapGesture(count: 2) {  // does not work in MacOS
      print("Line Double-Clicked")
    }   
  }
}

1

There are 1 best solutions below

0
Hongtron On

A workaround that works for me for selecting the row is to pass the selection as a binding to the Line view and add a single onTapGesture to change the selection binding to the index value. I am sure this is to do with layers of what is picking up the tapGesture. Putting both on the background color allows it to determine between single and double click.

struct Line: View {
  var index: Int
    @Binding var selectedRow: Int? // <- Adding a binding to the selection
  
  var body: some View {
    HStack (alignment: .top) {
      Image(systemName: "1.circle.fill")
        .onTapGesture (count: 2){
          print("Icon 1 Double-Clicked")
        }
        .onTapGesture (count: 1){
          print("Icon 1 Single-Clicked")
        }
      VStack (alignment: .leading){
        Text("Line: \(index)")
        Text("Some other Text")
      }
      Spacer()
      Image(systemName: "2.circle.fill")
        .onTapGesture (count: 2){
          print("Icon2 Double-Clicked")
        }
        .onTapGesture (count: 1){
          print("Icon2 Single-Clicked")
        }
    }
    .background(Color.green)
    .onTapGesture(count: 2) {  // does not work in MacOS
        print("Line \(index.description) Double-Clicked")
    }
    .onTapGesture(count: 1) {  // <- Add This
        selectedRow = index
        print("Selected Line is \(index.description)")
    }
  }
}