How to detect swipe in flutter
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
);
}
Sam Cromer
Updated on July 09, 2022Comments
-
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 about 5 yearsCan I wrap the entire screen? We want to have swipe right capabilities on the entire screen.
-
CopsOnRoad about 5 yearsI believe, you can do that too by wrapping your root widget (the one inside
body
ofScaffold
) -
Sam Cromer about 5 yearsThe swipe right is working but none of the screens content is showing up.
-
Taras Lukavyi about 4 yearsadd
child
to GestureDetector -
Kamlesh over 3 yearsundefined 'sensitivity'?
-
Vimal Rai over 3 yearsSensitivity is an integer used to perform an action when a user has swiped up to some extent.
-
Nizar B. over 3 yearsThis has nothing to do with detecting swipe.
-
b0rgBart3 over 3 yearsThis 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 over 3 yearsIf 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 over 3 yearsThanks, your solution saved my day, I can attach it to the multilevel pageview
-
Yavuz Tarhan over 3 yearsthanx, others call the func too many times
-
Luke Irvin over 2 yearsThis still detects diagonal drags. Is there a way to prevent that or to ignore those?
-
Luke Irvin over 2 yearsCould I get more context on these --> tapOperator(widget.settings.swipeUpOperator),
-
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 over 2 yearsdetails.velocity.pixelsPerSecond provides an offset for x and y values. Have you looked at those?
-
geisterfurz007 about 2 yearsNote: 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 almost 2 yearsThis idea is brilliant! Other answers triggers the swipe function many times but this is so good. Thanks!
-
JahidRatul almost 2 yearsvery nice , perfect one for swipe to widget