Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Longpress and list scrolling

Using SwiftUI (latest XCode and testing on IOS 13.3) I'm trying to implement a long press gesture on items in a list, to allow user interaction with the individual items. The problem is that when I set "onLongPressGesture" anywhere in the list (on items, on the list itself), the list cannot be scrolled anymore. I can easily get a simple tap to work but a long press blocks scrolling.

I've put together a small example that show this issue:

struct ContentView: View
{
  let data = [
    "Test 1","Test 2","Test 3","Test 4","Test 5",
    "Test 6","Test 7","Test 8","Test 9","Test 10",
    "Test 11","Test 12","Test 13","Test 14","Test 15",
    "Test 16","Test 17","Test 18","Test 19","Test 20"
  ]

  var body: some View
  {
    List
    {
      ForEach(data,id:\.self)
      {
        item in
        Text(item).onLongPressGesture{}
      }
    }
  }
}

If I try to drag the list pressing on any text, the list wont move. If I remove the longpress handler, it moves no matter where I press down.

like image 875
jensrodi Avatar asked Dec 21 '19 22:12

jensrodi


2 Answers

I asked this on the Apple Developer Forum as well and got a solution for the problem. If the view defines an onTapGesture handler before onLongPressGesture, the list will be scrollable while supporting long press on the individual items.

The onTapGesture handler can be empty as long as it is declared first.

struct ContentView: View
{
  let data = [
    "Test 1","Test 2","Test 3","Test 4","Test 5",
    "Test 6","Test 7","Test 8","Test 9","Test 10",
    "Test 11","Test 12","Test 13","Test 14","Test 15",
    "Test 16","Test 17","Test 18","Test 19","Test 20"
  ]

  var body: some View
  {
    List
    {
      ForEach(data,id:\.self)
      {
        item in
        Text(item).onTapGesture{}.onLongPressGesture{}
      }
    }
  }
}
like image 54
jensrodi Avatar answered Nov 05 '22 08:11

jensrodi


Referring @Jensrodi's solution as it works perfect, although you can experience a higher delay than what you would expect for a Long Press Gesture by adding a .onTapGesture before the .onLongPressGesture.

To mitigate this, you can use onLongPressGesture(minimumDuration:) to reduce/increase to a duration you are comfortable with.

See the example below

List {
    ForEach(0..<100) { x in
        Text("List number -\(x)")
            .onTapGesture{}.onLongPressGesture(minimumDuration: 0.2) { // Setting the minimumDuration to ~0.2 reduces the delay
                print("long press \(x)")
            }
    }
}
like image 6
Visal Rajapakse Avatar answered Nov 05 '22 08:11

Visal Rajapakse