How to Change Swiping direction of CupertinoPageRoute

Issue

I’m using Cupertino Page Route to produce the following Behavior

GIF of Swipe CupertinoRoute 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 :

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 :

GIF of Solution

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)

Leave a Reply

Your email address will not be published.