Search code examples
flutterflutter-navigation

Directly using Navigator class without MaterialApp in Flutter (initialization)


I'm trying to code a Navigator explicitly, instead of using the one under the hood of MaterialApp, in order to understand better how it works and to be able to eventually create highly customized navigation schemes.

The following code returns a Null check operator used on a null value error, though all fields that I'm aware are necessary to provide are provided. When the commented code is included, which then sets all settable Navigator fields, the error message still occurs.

import 'package:flutter/material.dart';

void main() {
  runApp(CustomNavigation());
}

class CustomNavigation extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Navigator(
      initialRoute: '/',
      onGenerateRoute: (routeSettings) {
        return MaterialPageRoute(
            builder: (context) => Container(
                  color: Colors.red,
                ));
      },
      onUnknownRoute: (routeSettings) =>
          MaterialPageRoute(builder: (BuildContext context) {
        return Container(
          color: Colors.green,
        );
      }),
      // key: GlobalKey(),
      // onGenerateInitialRoutes: (state, string) => [
      //   MaterialPageRoute(builder: (BuildContext context) {
      //     return Container(
      //       color: Colors.white,
      //     );
      //   }),
      // ],
      // onPopPage: (route, result) => true,
      // pages: [
      //   MaterialPage(
      //       child: Container(
      //     color: Colors.purple,
      //   ))
      // ],
      // observers: [NavigatorObserver()],
      // reportsRouteUpdateToEngine: true,
      // restorationScopeId: 'I am a string',
      // transitionDelegate: DefaultTransitionDelegate(),
    );
  }
}

What null value is causing this error message?


Solution

  • Got it! The Overlay widget (containing Routes that the Navigator manages the order of to create the experience of navigation, with Routes higher in the overlay painted after those lower in the overlay) requires textDirection information! The null value refers to the Directionlity.of(context) requested while the Overlay is being rendered. Adding a Directionality widget solves this issue, as in the fixed code here:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(CustomNavigation());
    }
    
    class CustomNavigation extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Directionality(
          textDirection: TextDirection.ltr,
          child: Navigator(
              onGenerateRoute: (routeSettings) {
            return MaterialPageRoute(
                builder: (context) => Container(
                      color: Colors.red,
                    ));
          }),
        );
      }
    }
    

    (To turn this minimal working example for null value debugging into something useful / custom navigation, use a switch statement on routeSettings.name in onGenerateRoute and write a class extending PageRoute to use in place of MaterialPageRoute.)