Search code examples
flutterdartflutter-navigation

How to set the property pageRouteBuilder of WidgetsApp in Flutter


I'm trying to understand how navigation in Flutter works at a basic level, beyond the Material design convenience widgets, in order to implement a non-standard navigation scheme.

I've been playing with the code from the answer here, and edited the build method from that code to be as follows, setting the routes and pageRouteBuilder properties to be non-null.

@override
 Widget build(BuildContext context) {
   return new WidgetsApp(
       onGenerateRoute: generate,
       pageRouteBuilder: (RouteSettings settings, WidgetBuilder builder) {
         return MaterialPageRoute(builder: (context) => Container(color: Colors.blue,));
         },
       onUnknownRoute: unKnownRoute,
       textStyle: const TextStyle(),
       initialRoute: "/",
       routes: <String, WidgetBuilder> {
         '/test': (BuildContext context) => Container(
           child: Text('test'), 
           color: Colors.green,
         ),
       },
       color: Colors.red);
 }

This throws the error

Error: The argument type 'MaterialPageRoute Function(RouteSettings, Widget Function(BuildContext))' can't be assigned to the parameter type 'PageRoute Function(RouteSettings, Widget Function(BuildContext))'

(I originally used a PageRoute widget in place of the MaterialPageRoute widget, but then also received the error that abstract classes could not be instantiated, so switched to MaterialPageRoute for convenience*, imagining that it would be an implementation of PageRoute.

*Rather than writing a new implementation of PageRoute for this toy example.)

I can't figure out how to fix this, as, as far as I can tell, the argument and parameter type are equivalent, and I can't find any examples on how to set the pageRouteBuilder property online. An explanation of why this error is occurring or a fix to this toy example would be greatly appreciated.


Solution

  • After poking around in material/app.dart to find how pageRouteBuilder is set there (if using Android Studio, write MaterialApp() anywhere, hover and Ctrl+click once underline appears, then search for 'pageRouteBuilder' in the file that opens), I have found that this can be fixed with

     @override
      Widget build(BuildContext context) {
        final MaterialPageRoute test = MaterialPageRoute<int>(builder: (context) {
          return Container();
        });
    
        return new WidgetsApp(
            onGenerateRoute: generate,
            pageRouteBuilder: <T>(RouteSettings settings, WidgetBuilder builder) {
              return MaterialPageRoute(builder: builder, settings: settings);
            },
            onUnknownRoute: unKnownRoute,
            textStyle: const TextStyle(),
            initialRoute: "/",
            routes: <String, WidgetBuilder>{
              '/test': (BuildContext context) => Container(
                    child: Text('test'),
                    color: Colors.green,
                  ),
            },
            color: Colors.red);
      }
    

    If I learn why <T> makes sense in this context in future, I'll edit this and explain as much here.