Reputation: 699
I want to click an item menu (PopupMenuItem) and go to another route using Navigator.push but context is undefined inside the method.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
final List<Choice> choices = const <Choice>[
const Choice(title: 'Settings', icon: Icons.settings),
const Choice(title: 'Log out', icon: Icons.exit_to_app),
];
@override
Widget build(BuildContext context) {
final title = 'MyTitle';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
actions: <Widget>[
PopupMenuButton<Choice>(
onSelected: onItemMenuPress,
itemBuilder: (BuildContext context) {
return choices.map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Row(
children: <Widget>[
Icon(
choice.icon,
),
Container(
width: 10.0,
),
Text(
choice.title,
),
],
));
}).toList();
},
),
],
),
body: Text("Hello world")
),
);
}
void onItemMenuPress(Choice choice) {
if (choice.title == 'Log out') {
print("Logout");
Navigator.push(context, MaterialPageRoute(builder: (context) => LogoutRoute()));
}
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
class LogoutRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Logout"),
),
body: Center(
child: Text("Screen"),
),
);
}
}
I have tried to pass a context in onItemMenuPress in this way:
void onItemMenuPress(Choice choice, BuildContext context)
but:
onSelected: onItemMenuPress(context)
is not working.
Neither this approach works:
onSelected: (Choice c) { Navigator.push(context, MaterialPageRoute(builder: (context) => LogoutRoute())); }
I was following this tutorial: https://medium.com/flutter-community/building-a-chat-app-with-flutter-and-firebase-from-scratch-9eaa7f41782e
and there is a snippet of his code (similar to mine) that seems to work for him: https://github.com/duytq94/flutter-chat-demo/blob/master/lib/main.dart
I refer to line 235 (onSelected) and lines 199-205 (actual onItemMenuPress method)
How is it possible? How can I salve? Thanks
Upvotes: 2
Views: 2210
Reputation: 994
It happens because your flutter SDK and dark SDK is not working properly. you can solve this issues upgrading your flutter sdk. go to the terminal and type
flutter upgrade --force
after that your fluter sdk and dark sdk will be upgrade, after the installation complete you will be fine.
Upvotes: 0
Reputation: 51176
Here you have :
MyApp <------ context
--> MaterialApp
(--> Navigator built within MaterialApp)
--> Scaffold
--> App Bar
--> ...
So when you're using the context to find the Navigator, you're using a context for the MyApp which isn't under the navigator.
so we can either make a new Stateless or Stateful Widget subclass to contain your Scaffold
, as the build function within those will point at that level instead, or we can use a Builder
and define the builder callback (which has a context pointing at the Builder) to return the Scaffold
.
Working Code we created new subclass - HomeScreen
:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final title = 'MyTitle';
return MaterialApp(
title: title,
home: HomeScreen(title),
);
}
}
class HomeScreen extends StatelessWidget {
final String title;
HomeScreen(this.title);
final List<Choice> choices = const <Choice>[
const Choice(title: 'Settings', icon: Icons.settings),
const Choice(title: 'Log out', icon: Icons.exit_to_app),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
actions: <Widget>[
PopupMenuButton<Choice>(
onSelected: (val) => onItemMenuPress(val, context),
itemBuilder: (BuildContext context) {
return choices.map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Row(
children: <Widget>[
Icon(
choice.icon,
),
Container(
width: 10.0,
),
Text(
choice.title,
),
],
));
}).toList();
},
),
],
),
body: Text("Hello world"));
}
void onItemMenuPress(Choice choice, BuildContext context) {
if (choice.title == 'Log out') {
print("Logout");
Navigator.push(
context, MaterialPageRoute(builder: (context) => LogoutRoute()));
}
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
class LogoutRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Logout"),
),
body: Center(
child: Text("Screen"),
),
);
}
}
Upvotes: 3