How to detect swipe in flutter

53,439

Solution 1

Use GestureDetector.onPanUpdate:

GestureDetector(
  onPanUpdate: (details) {
    // Swiping in right direction.
    if (details.delta.dx > 0) {}
  
    // Swiping in left direction.
    if (details.delta.dx < 0) {}
  },
  child: YourWidget(),
)

To cover all the area (passing the parent constraints to the widget), you can include SizedBox.expand.

SizedBox.expand(
  child: GestureDetector(
    onPanUpdate: (details) {
      // Swiping in right direction.
      if (details.delta.dx > 0) {}

      // Swiping in left direction.
      if (details.delta.dx < 0) {}
    },
    child: YourWidget(),
  ),
)

Solution 2

Wrap your Widget in GestureDetector and use onHorizontalDragUpdate as,

GestureDetector(
    onHorizontalDragUpdate: (details) {  
        // Note: Sensitivity is integer used when you don't want to mess up vertical drag
        int sensitivity = 8;
        if (details.delta.dx > sensitivity) {
            // Right Swipe
        } else if(details.delta.dx < -sensitivity){
            //Left Swipe
        }
    }
);

Or if you're looking for a vertical swipe, you can use this code:

GestureDetector(
    onVerticalDragUpdate: (details) {
        int sensitivity = 8;
        if (details.delta.dy > sensitivity) {
            // Down Swipe
        } else if(details.delta.dy < -sensitivity){
            // Up Swipe
        }
    }
)

Solution 3

To piggy back off of @Vimal Rai's answer. I found that onHorizontalDragUpdate calls the function with every update. That could lead to unwanted behavior in your app. If you want the function to be called just once upon swiping, go with OnHorizontalDragEnd:

GestureDetector(
    onHorizontalDragEnd: (DragEndDetails details) {
      if (details.primaryVelocity > 0) {
        // User swiped Left
      } else if (details.primaryVelocity < 0) {
        // User swiped Right
      }
    }
);

Solution 4

In some cases GestureDetector does not fire gesture events if it's used as a child or parent of other scrollable widgets. Maybe a better! way to detect any gesture is to use Listener widget.

Listener(
   onPointerMove: (moveEvent){
      if(moveEvent.delta.dx > 0) {
          print("swipe right");
      }
   }
    child: PageView(...) // or any other widget
)

Solution 5

This is my solution using GestureDetector. I put the handler inside onPanEnd, as onPanUpdate gets called multiple times when the swiping is in progress.

@override
  Widget build(BuildContext context) {
    String? swipeDirection;

    return GestureDetector(
      onPanUpdate: (details) {
        swipeDirection = details.delta.dx < 0 ? 'left' : 'right';
      },
      onPanEnd: (details) {
        if (swipeDirection == null) {
          return;
        }
        if (swipeDirection == 'left') {
          //handle swipe left event
        }
        if (swipeDirection == 'right') {
          //handle swipe right event
        }
      },
      child: //child widget
    );
  }
Share:
53,439
Sam Cromer
Author by

Sam Cromer

Updated on July 09, 2022

Comments

  • Sam Cromer
    Sam Cromer almost 2 years

    I've tried using the swipe detector plugin for flutter to achieve navigating to a new screen on swipe right but it's not working, no errors are thrown and the breakpoint is never hit when I debug it. I looked into the GestureDector but I wasn't sure it would work for a swipe right scenario, we want it to navigate to a screen when anywhere on the screen is swiped right.

    Here's my code using the plugin

     @override
     Widget build(BuildContext context){
    return new Scaffold(
     appBar : LBAppBar().getAppBar(),
      //drawer: new LBDrawer().getDrawer(),
     body:  Container(
    decoration: BoxDecoration(
        gradient: new LinearGradient(
            colors: [Color.fromRGBO(1,89,99, 1.0), Colors.grey],
            begin: Alignment.bottomLeft,
            end: Alignment.topRight
        )
    ),
     child: 
     SwipeDetector(
         onSwipeRight: () {
           Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new WidgetsPage())
            ); },
      child: Column(
      mainAxisAlignment: MainAxisAlignment.center,    
      children:[
        Row(
                children: [
              Container(
                margin: EdgeInsets.only(left: 20.0,top: 10.0, bottom: 10.0, right:30.0),
                child: Column(
      children: <Widget>[
    
    
    
                Text("Hi ${user.firstName}, Today is " + formatDate(), style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.bold, fontSize: 19.0 
     )),
    
    
    
    
            ],
    
             ),
                     ),
                      ]
                ),
    
          Row(
            //ROW 1
            children: [
              Container(
                margin: EdgeInsets.only(left: 30.0,top: 60.0, bottom: 30.0, right:30.0),
                child: Column(
          children: <Widget>[
               GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.checkSquare,
                     size: 50.0,
                     color: Colors.white70,
             ),
                  onTap: () {
                            Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new CheckIn()));
                          }),
                    Text("Check In", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.normal ))
      ],
     ),
                  ),
                  Container(
               margin: EdgeInsets.only(left: 50.0,top: 60.0, bottom: 30.0, right:30.0),
                    child: Column(
          children: <Widget>[
               GestureDetector(
    
                     child: Icon(
                     FontAwesomeIcons.list,
                     size: 50.0,
                      color: Colors.white70,
             ),
                  onTap: () {
                        Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new DayAtAGlance()));
                          }),
                Text("My Day", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.normal ))
    ],
     ),
                   ),
                Container(
               margin: EdgeInsets.only(left: 30.0,top: 60.0, bottom: 30.0, right:30.0),
                child: Column(
      children: <Widget>[
           GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.phone,
                     size: 45.0,
                      color: Colors.white70,
             ),
                  onTap: () {
                        Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new CommunicationLinks()));
                          }),
                  Text("Communication", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.normal ))
      ],
     ),
                 ),
                 ]
                  ),
             Row(//ROW 2
              children: [
            Container(
               margin: EdgeInsets.only(left: 32.0,top: 50.0, bottom: 30.0),
                child: Column(
      children: <Widget>[
           GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.dollarSign,
                     size: 50.0,
                      color: Colors.white70,
               ),
                  onTap: () {
                       Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new Budget()));
                          }),
                Text("Budget", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.normal ))
    ],
     ),
    
                  ),
            Container(
               margin: EdgeInsets.only(left: 75.0, top: 50.0, bottom: 30.0, right: 30.0),
                child: Column(
      children: <Widget>[
           GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.trophy,
                     size: 50.0,
                      color:  Colors.white70,
             ),
                  onTap: () {
                        print("Pressed");
                          }),
                Text("Goals", style: new TextStyle( color:  Colors.white70, fontWeight: FontWeight.normal ))
    ],
    ),
    
                ),
             Container(
               margin: EdgeInsets.only(left: 50.0, top: 50.0, bottom: 30.0, right: 20.0),
                child: Column(
      children: <Widget>[
           GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.calendar,
                     size: 50.0,
                      color: Colors.white70,
             ),
                  onTap: () {
    
                       Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new CalendarsPage()));
                          }),
                Text("Calendar", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.normal ))
      ],
    ),
                )
             ]),
          Row(// ROW 3
              children: [
            Container(
               margin: EdgeInsets.only(left: 30.0, top: 50.0, bottom: 30.0, right: 30.0),
                child: Column(
      children: <Widget>[
           GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.comments,
                     size: 50.0,
                      color: Colors.white70,
             ),
                  onTap: () {
                        print("Pressed");
                          }),
                Text("Community", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.normal ))
      ],
    ),
    
                ),
            Container(
               margin: EdgeInsets.only(left: 20.0, top: 50.0, bottom: 30.0, right: 20.0),
                child: Column(
      children: <Widget>[
           GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.shoppingCart,
                     size: 50.0,
                     color: Colors.white70,
             ),
                  onTap: () {
                         Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new ShoppingList()));
                          }),
                Text("Shopping", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.normal ))
      ],
    ),
    
                  ),
              Container(
               margin: EdgeInsets.only(left: 50.0, top: 50.0, bottom: 30.0, right: 40.0),
                child: Column(
      children: <Widget>[
           GestureDetector(
                     child: Icon(
                     FontAwesomeIcons.solidCheckSquare,
                     size: 50.0,
                      color: Colors.white70,
             ),
                  onTap: () {
                        Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context) => new CheckOut()));
                          }),
                Text("Check Out", style: new TextStyle( color: Colors.white70, fontWeight: FontWeight.bold ))
    ],
    ),
    
                ),
          ]),
        ],
          ),
       )
    
    
     )
    
    
       );
    
  • Sam Cromer
    Sam Cromer about 5 years
    Can I wrap the entire screen? We want to have swipe right capabilities on the entire screen.
  • CopsOnRoad
    CopsOnRoad about 5 years
    I believe, you can do that too by wrapping your root widget (the one inside body of Scaffold)
  • Sam Cromer
    Sam Cromer about 5 years
    The swipe right is working but none of the screens content is showing up.
  • Taras Lukavyi
    Taras Lukavyi about 4 years
    add child to GestureDetector
  • Kamlesh
    Kamlesh over 3 years
    undefined 'sensitivity'?
  • Vimal Rai
    Vimal Rai over 3 years
    Sensitivity is an integer used to perform an action when a user has swiped up to some extent.
  • Nizar B.
    Nizar B. over 3 years
    This has nothing to do with detecting swipe.
  • b0rgBart3
    b0rgBart3 over 3 years
    This works great- I set the sensitivity to 8. But I'm curious if there is a standard amount that would be considered a "swipe".
  • Viraj D
    Viraj D over 3 years
    If this code is being triggered many times on swiping right then you can use this solution (Probably there is a better way to do this but this works for me) int test = 0 if (details.delta.dx > 0 && test == 0) { test += 1 /*your code*/ } and on swipe left set the variable (test) to 0 again
  • malik kurosaki
    malik kurosaki over 3 years
    Thanks, your solution saved my day, I can attach it to the multilevel pageview
  • Yavuz Tarhan
    Yavuz Tarhan over 3 years
    thanx, others call the func too many times
  • Luke Irvin
    Luke Irvin over 2 years
    This still detects diagonal drags. Is there a way to prevent that or to ignore those?
  • Luke Irvin
    Luke Irvin over 2 years
    Could I get more context on these --> tapOperator(widget.settings.swipeUpOperator),
  • Bugzilla
    Bugzilla over 2 years
    @LukeIrvin oops, that wasn't supposed to be there. It's just the function to be executed when a swipe is detected
  • Luis
    Luis over 2 years
    details.velocity.pixelsPerSecond provides an offset for x and y values. Have you looked at those?
  • geisterfurz007
    geisterfurz007 about 2 years
    Note: If the user dragged, then stopped their finger for a second then lift their finger, the reported velocity in the details will be 0.
  • batuhankrbb
    batuhankrbb almost 2 years
    This idea is brilliant! Other answers triggers the swipe function many times but this is so good. Thanks!
  • JahidRatul
    JahidRatul almost 2 years
    very nice , perfect one for swipe to widget