Issue
I’m using Cupertino Page Route to produce the following Behavior
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//doesn't do what I want to do
GestureDetector(
onTap: () => Navigator.of(context).pushNamed(settingsPage),
onPanUpdate: (details){
if(details.delta.dx < 0){
Navigator.of(context).pushNamed(settingsPage);
}
},
child: Icon(Icons.settings),
),
//Not my concern for now
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications, color: Colors.black),
),
//Does what I want it to do
GestureDetector(
onTap: () => Navigator.of(context).pushNamed(messages),
child: Icon(Icons.message),
),
],
),
It allows me to swipe from Left to Right to close the Message Screen
Unfortunately it does not allow me to close the Settings Screen by swiping from Right to Left
Anyone one knows how to change the direction of the swipe for CupertinoPageRoute or mimic it’s behavior with an other Solution ?
Solution
I don’t think you can easily change the swiping direction of CupertinoRoute but I’ve found two easy solutions for you :
- You could either use a PageView Widget – which allows you to swipe between screens
Or – better solution for your specific situation :
- You could instead use the page_transition Package with a Swipe Direction Detector
This Second Solution will best reproduce the behavior of CupertinoPageRoute
- in addition it will provide you with animations going from HomeScreen to Settings/Messages but also back to your HomeScreen :
This is how you could implement this second solution shown in the GIF above into your App :
import 'package:page_transition/page_transition.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
_HomeScreen createState() => _HomeScreen();
}
class _HomeScreen extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
automaticallyImplyLeading: false,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () => Navigator.push(
context,
//Use Page Transition left to right here
PageTransition(
// duration: Duration(seconds: 1),
type: PageTransitionType.leftToRightWithFade,
child: SettingsScreen(),
inheritTheme: true,
ctx: context),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: const Icon(Icons.settings, color: Colors.black),
)),
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications, color: Colors.black),
),
GestureDetector(
onTap: () => Navigator.push(
context,
//Use Page Transition right to left here
PageTransition(
// duration: Duration(seconds: 1),
type: PageTransitionType.rightToLeftWithFade,
child: const MessageScreen(),
inheritTheme: true,
ctx: context),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: const Icon(Icons.message, color: Colors.black),
)),
],
),
),
//body
body: Container(),
);
}
}
Then in your Settings/Messages Screens just implement a GestureDetector
which will trigger on Swipe
It will Navigator.pop (close) your screen – & Flutter will take care of the reverse animation
class SettingsScreen extends StatefulWidget {
const SettingsScreen({Key? key}) : super(key: key);
@override
_SettingsScreen createState() => _SettingsScreen();
}
class _SettingsScreen extends State<SettingsScreen> {
@override
Widget build(BuildContext context) {
return GestureDetector(
// This is where you detect swiping from right to left
onPanUpdate: (details) {
if (details.delta.dx < -10) {
// Upon swiping detection it then pops the screen - reverse animation happens without additional code
Navigator.pop(context);
}
},
child: const Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(child: const Text("🥸 Settings")),
));
}
}
// Same code here for your MessageScreen but with opposite swipe gesture detection (left to right)
class MessageScreen extends StatefulWidget {
const MessageScreen({Key? key}) : super(key: key);
@override
_MessageScreen createState() => _MessageScreen();
}
class _MessageScreen extends State<MessageScreen> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: (details) {
if (details.delta.dx > 10) {
Navigator.pop(context);
}
},
child: const Scaffold(
backgroundColor: Colors.redAccent,
body: Center(child: const Text("😎 Messages")),
));
}
}
That’s it ! – the only down side to this method is once the swipe has been detected there is no way to cancel it
—- upon long discussion with the user – comments bellow have been addressed above & question edited
Answered By – Aristidios
Answer Checked By – Clifford M. (FlutterFixes Volunteer)