EliaTolin
EliaTolin

Reputation: 648

Long press time consider for GestureDetector

Problem:

I built minesweeper and 350ms is too much to trigger the longPress event, I need more speed. I need implement time consider for GestureDetector, i need 200ms for detect long press event.

How my system build:

Every button use onTap and LongPress event.

My test:

I try to use this package: XGestureDetector

But it works bad because in different device not works.

I had seen but the onTap event does not work this way: StackOverFlow Answer

I need a method to solve my problem.

Upvotes: 3

Views: 7546

Answers (3)

ImaginaryProgramming
ImaginaryProgramming

Reputation: 66

I've sometimes had some issues with GestureDetector, so here's an alternate solution that uses a Listener.

class CustomHoldListener extends StatefulWidget {
  const CustomHoldListener({
    this.holdDuration = const Duration(milliseconds: 350),
    this.onTap,
    this.onHold,
    super.key,
  });

  final Duration holdDuration;
  final VoidCallback? onTap;
  final VoidCallback? onHold;

  @override
  State<CustomHoldListener> createState() => _CustomHoldListenerState();
}

class _CustomHoldListenerState extends State<CustomHoldListener> {
  Duration? lastPointerDownTime;

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: (event) {
        lastPointerDownTime = event.timeStamp;
      },
      onPointerUp: (event) {
        if (lastPointerDownTime != null) {
          if (event.timeStamp - lastPointerDownTime! > widget.holdDuration) {
            widget.onHold?.call();
            return;
          }
        }
        
        widget.onTap?.call();
      },
    );
  }
}

Upvotes: 1

EliaTolin
EliaTolin

Reputation: 648

Using @salihgueler answer, I found the solution:

class MyWidget extends StatefulWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late Timer _timer;
  bool isLongPressed = false; 
  
  void _startOperation() {
    _timer = Timer(const Duration(milliseconds: 200), () {
      print('LongPress Event');
      isLongPressed= true; 
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (_) {
        _startOperation();    
      },
      onTapUp: (_) {
        _timer.cancel();
        if(!isLongPressed)
        {
          print("Is a onTap event");
        }
        else 
        {
          isLongPressed = false; 
        }
      },
      child: Text(
        'Hello, World!',
        style: Theme.of(context).textTheme.headline4,
      ),
    );
  }
}

Upvotes: 0

salihgueler
salihgueler

Reputation: 3632

There are multiple ways of doing it. I will show you something that I came up with that can help you start out with.

It starts a timer on each tap to the child and cancels it when you take your hand off. It takes advantage of onTapDown and onTapUp from GestureDetector, a widget that you are familiar from Flutter ecosystem.


class MyWidget extends StatefulWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late Timer _timer;

  void _startOperation() {
    _timer = Timer(const Duration(milliseconds: 200), () {
      print('Do something after delay');
    });
  }
  
  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (_) {
        _startOperation();    
      },
      onTapUp: (_) {
        _timer.cancel();
      },
      child: Text(
        'Hello, World!',
        style: Theme.of(context).textTheme.headline4,
      ),
    );
  }
}

Upvotes: 2

Related Questions