Search code examples
fluttergesture

How to have a callback function called onTap, another onTapDown, and another onTapUp without overlap?


I have this UI: enter image description here When user taps on right side we go to the next story, left we go to previous and holding down anywhere should stop the automatic loading on top. I am currently using GestureDetectors and using the three callbacks

  • onTap To go to next or previous story
  • onTapDown To pause the loader
  • onTapUp To resume the loader

The problem is onTap gets called with onTapUp so when I try to pause for example by holding down on the right side, it would immediately go to the next story after I lift my finger.


Solution

  • Let's try the below solution, I tested it and it works quite well in your case.

    Below is a custom GestureDetector widget that allows us to set the duration for onLongPressStart and onLongPressEnd

    import 'package:flutter/material.dart';
    import 'package:flutter/gestures.dart';
    
    class CustomGestureLongPress extends StatelessWidget {
      final Widget? child;
      final Duration duration;
      final GestureLongPressStartCallback onLongPressStart;
      final GestureLongPressEndCallback onLongPressEnd;
      final VoidCallback? onLongPress;
    
      const CustomGestureLongPress({
        super.key,
        this.child,
        required this.duration,
        required this.onLongPressStart,
        required this.onLongPressEnd,
        this.onLongPress,
      });
    
      @override
      Widget build(BuildContext context) {
        return RawGestureDetector(
          behavior: HitTestBehavior.translucent,
          gestures: <Type, GestureRecognizerFactory>{
            LongPressGestureRecognizer: GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
                  () => LongPressGestureRecognizer(duration: duration), (instance) {
                    instance.onLongPress = () {
                      print("Parent onLongPress");
                      onLongPress?.call();
                    };
                    instance.onLongPressStart = (details) {
                      print("Parent onLongPressStart");
                      onLongPressStart.call(details);
                    };
                    instance.onLongPressEnd = (details) {
                      print("Parent onLongPressEnd");
                      onLongPressEnd.call(details);
                    };
                  },
            ),
          },
          child: child,
        );
      }
    }`
    

    And the usage of the custom widget

    CustomGestureLongPress(
                duration: const Duration(milliseconds: 200),
                onLongPressStart: (_) {
                  //TODO Pause the loader
                },
                onLongPressEnd: (_) {
                  //TODO Resume the loader
                },
                child: Stack(
                    children: [
                      GestureDetector(
                        onTap: () {
                          //TODO Go to previous story
                        },
                        child: Align(
                          alignment: Alignment.centerLeft,
                          child: Container(
                            width: 50.w,
                            color: Colors.transparent,
                          ),
                        )
                      ),
                      GestureDetector(
                        onTap: () {
                          //TODO Go to next story
                        },
                        child: Align(
                          alignment: Alignment.centerRight,
                          child: Container(
                            width: 50.w,
                            color: Colors.transparent,
                          ),
                        )
                      )
                    ]
                ),
              )