IrishGringo
IrishGringo

Reputation: 4054

how to use CupertinoPageRoute and named routes in flutter?

I want to use a CupertinoPageRoute instead of the Navigator.pushNamed with a routes array in MaterialApp. Navigator.pushNamed(context, p01.routeName); works fine. But I want to accomplish two items.

  1. I want the navigation to be Cupertino Style in Android. Right To left, instead of Bottom to Top.

  2. Navigation will go very deep, and I want to include a return button... like this. Navigator.popUntil(context, ModalRoute.withName('/')); where I can return to specific locations in the navigation Stack.

HOW can I use routes, namedRoutes and CupertinoPageRoute(builder: (context) => p02.routeName);

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'p01.dart';
import 'p02.dart';
import 'p03.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
      initialRoute: '/',
//      routes: {
//        '/p01' : (context) => p01(),
//        '/p02' : (context) => p02(),
//        '/p03' : (context) => p03(),
//      },
//***** .  this is what I am trying to use for routes.
      routes: <String, WidgetBuilder>{
        p01.routeName: (BuildContext context) => new p01(title: "p01"),
        p02.routeName: (BuildContext context) => new p02(title: "p02"),
        p03.routeName: (BuildContext context) => new p03(title: "p03"),
      },
    );
  }
}

...

            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                child: Text(" cup P01"),
                onPressed: () {
                  print("p01 was pressed");
                  //Navigator.pushNamed(context, p01.routeName);
//                  CupertinoPageRoute(builder: (context) => AA02Disclaimer()),
                  //CupertinoPageRoute(builder: (context) => p02());
//                  CupertinoPageRoute(  p02.routeName );

                  // p02.routeName: (BuildContext context) => new p02(title: "p02"),
//**** . this is the code I am trying to make work...
                  CupertinoPageRoute(builder: (context) => p02.routeName);

                },
              ),
            ),

======= This is code to return to the root.

              Padding(
                padding: const EdgeInsets.all(8.0),
                child: RaisedButton(
                  child: Text("/"),
                  onPressed: () {
                    print("/ was pressed");
//                  Navigator.pushNamed(context, p03.routeName);
                    Navigator.popUntil(context, ModalRoute.withName('/'));
                  },
                ),
              ),

Upvotes: 25

Views: 27600

Answers (2)

Isaya Osward
Isaya Osward

Reputation: 11

The simplest way is to add pageTransitionsTheme in your ThemeData, here is how you can achieve that behavior globally. Now every navigation you make will behave like an iOS transition

import 'package:flutter/material.dart';
import 'p01.dart';
import 'p02.dart';
import 'p03.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
       pageTransitionsTheme: const PageTransitionsTheme(
         builders: {
           TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
           TargetPlatform.android: CupertinoPageTransitionsBuilder()
    },
  ),
      primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
      initialRoute: '/',
        routes: {
          '/p01' : (context) => p01(),
          '/p02' : (context) => p02(),
          '/p03' : (context) => p03(),
        },
    );
  }
}

Upvotes: 0

NiklasPor
NiklasPor

Reputation: 9815

TL;DR: Use onGenerate of MaterialApp / CupertinoApp to use custom routes. For example CupertinoPageRoute. If you are already using the Cupertino-Style consider using CupertinoApp, which automatically uses the CupertinoPageRoute.

I've split this answer in two solutions, one with the default MaterialAppand one with the CupertinoApp(using Cupertino-Style):


Keeping your style (MaterialApp):

If you want to keep the MaterialApp as your root widget you'll have to replace the routes attribute of your MaterialApp with an onGenerate implementation:

Original:

routes: {
  '/': (_) => HomePage(),
  'deeper': (_) => DeeperPage(),
}

Changed with onGenerate:

onGenerateRoute: (RouteSettings settings) {
  switch (settings.name) {
    case '/':
      return CupertinoPageRoute(
          builder: (_) => HomePage(), settings: settings);
    case 'deeper':
      return CupertinoPageRoute(
          builder: (_) => DeeperPage(), settings: settings);
  }
}

Now onGenerate handles the routing manually and uses for each route an CupertinoPageRoute. This replaces the complete routes: {...} structure.

Quick standalone example:

MaterialApp Solution Example

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      onGenerateRoute: (RouteSettings settings) {
        switch (settings.name) {
          case '/':
            return CupertinoPageRoute(
                builder: (_) => HomePage(), settings: settings);
          case 'deeper':
            return CupertinoPageRoute(
                builder: (_) => DeeperPage(), settings: settings);
        }
      },
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Material!'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Take me deeper!'),
          onPressed: () => Navigator.pushNamed(context, 'deeper'),
        ),
      ),
    );
  }
}

class DeeperPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Material!'),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          RaisedButton(
            child: Text('Home :)'),
            onPressed: () =>
                Navigator.popUntil(context, ModalRoute.withName('/')),
          ),
          RaisedButton(
            child: Text('Deeper!'),
            onPressed: () => Navigator.pushNamed(context, 'deeper'),
          ),
        ],
      ),
    );
  }
}

Cupterino Style (CupertinoApp):

If you want to use the Cupertino-Style anyway, I would suggest to use the CupertinoApp widget instead of the MaterialApp widget (like already suggested in a comment by @anmol.majhail).

Then the default chosen navigation will always use the CupertinoPageRoute.

Quick standalone example:

CupertinoApp Demo

import 'package:flutter/cupertino.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      routes: {
        '/': (_) => HomePage(),
        'deeper': (_) => DeeperPage(),
      },
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: Center(
        child: CupertinoButton(
          child: Text('Take me deeper!'),
          onPressed: () => Navigator.pushNamed(context, 'deeper'),
        ),
      ),
    );
  }
}

class DeeperPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          CupertinoButton(
            child: Text('Home :)'),
            onPressed: () =>
                Navigator.popUntil(context, ModalRoute.withName('/')),
          ),
          CupertinoButton(
            child: Text('Deeper!'),
            onPressed: () => Navigator.pushNamed(context, 'deeper'),
          ),
        ],
      ),
    );
  }
}

Upvotes: 42

Related Questions