StackOverflow community!
What I'm trying to build is a mobile/web application in Flutter with a static "always open" drawer on the web.
So what I did is I've created and router (with Fluro) and use it in the onGenerateRoute function of my MaterialApp. The child will be created from the router and I'll pass it to the "MainLayout".
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'MyApp',
theme: appTheme,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
FlutterI18nDelegate(
translationLoader: FileTranslationLoader(
basePath: 'assets/i18n',
fallbackFile: 'de_DE',
useCountryCode: true),
),
],
supportedLocales: [
const Locale('en', 'US'), // English
const Locale('de', 'DE'), // German
],
initialRoute: NavUtils.initialUrl,
onGenerateRoute: router.generator,
navigatorKey: _navigatorKey,
builder: (context, child) {
return MultiBlocProvider(
providers: [
BlocProvider.value(
value: _authenticationBloc,
),
BlocProvider.value(
value: _userSettingsBloc,
),
BlocProvider.value(
value: _organizationBloc,
),
BlocProvider.value(
value: _reportsBloc,
),
],
child: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is AuthenticationAuthenticated) {
return MainLayout(
child: child,
drawerKey: _drawerKey,
navigatorKey: _navigatorKey,
);
} else {
return Scaffold(
backgroundColor: mainBackground,
drawer: DrawerMenu(
navigatorKey: _navigatorKey,
drawerKey: _drawerKey,
),
body: SafeArea(
child: child,
),
);
}
},
),
);
},
);
}
and the content of my MainLayout()
class MainLayout extends StatelessWidget {
final Widget child;
final GlobalKey<ScaffoldState> drawerKey;
final GlobalKey<NavigatorState> navigatorKey;
MainLayout(
{Key key,
@required this.child,
@required this.drawerKey,
@required this.navigatorKey})
: super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
key: drawerKey,
backgroundColor: mainBackground,
drawer: MediaQuery.of(context).size.width >= 769
? null
: DrawerMenu(
navigatorKey: navigatorKey,
drawerKey: drawerKey,
),
body: SafeArea(
child: Container(
child: Row(
children: <Widget>[
MediaQuery.of(context).size.width >= 769
? DrawerMenu(
navigatorKey: navigatorKey,
drawerKey: drawerKey,
)
: Container(),
Expanded(
child: child,
),
],
),
),
),
);
}
}
The problem I have is, that ie. my DrawerMenu() can't find the navigator in the context. Leading me to problems like I can't use any tooltip widget because it's not finding the overlay.
════════ Exception caught by widgets library ═══════════════════════════════════
No Overlay widget found.
The relevant error-causing widget was
Tooltip
As soon as I'll wrap my whole MaterialApp in another MaterialApp it's working fine, but I destroy my routing.
Can anybody help me with this? Is this enough information to even provide any help?
Update
With your question and your answer here on StackOverflow I figured out, that I have to use this different. What I did is to "extract" the whole stuff and make created a Navigator in the Scaffold, like this:
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'MyApp',
theme: appTheme,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
FlutterI18nDelegate(
translationLoader: FileTranslationLoader(
basePath: 'assets/i18n',
fallbackFile: 'de_DE',
useCountryCode: true),
),
],
supportedLocales: [
const Locale('en', 'US'), // English
const Locale('de', 'DE'), // German
],
initialRoute: NavUtils.initialUrl,
onGenerateRoute: (RouteSettings settings) {
_navigatorKey.currentState.popAndPushNamed(settings.name);
},
home: Builder(
builder: (context) => MultiBlocProvider(
providers: [
BlocProvider.value(
value: _authenticationBloc,
),
BlocProvider.value(
value: _userSettingsBloc,
),
BlocProvider.value(
value: _organizationBloc,
),
BlocProvider.value(
value: _reportsBloc,
),
],
child: Scaffold(
key: _drawerKey,
backgroundColor: mainBackground,
drawer: MediaQuery.of(context).size.width >= 769
? null
: DrawerMenu(
navigatorKey: _navigatorKey,
drawerKey: _drawerKey,
),
body: SafeArea(
child: Container(
child: Row(
children: <Widget>[
MediaQuery.of(context).size.width >= 769
? DrawerMenu(
navigatorKey: _navigatorKey,
drawerKey: _drawerKey,
)
: Container(),
Expanded(
child: Navigator(
key: _navigatorKey,
initialRoute: NavUtils.initialUrl,
onGenerateRoute: router.generator,
),
),
],
),
),
),
),
),
),
);
}
The only problem now is, how do I get the URL, a user enters in the browser address bar, to my navigator.
For now I'm using _navigatorKey.currentState.popAndPushNamed(settings.name);
in my MaterialApp but this removes the URL in the address bar after hitting enter. (But it actually navigates to the correct page)
Is there a way to keep this consistent?