I am new to Flutter and I am trying to build an app. Which will have multiple pages. When ever I am trying to navigate to second screen it giving me exception. I saw many videos on how to navigate to different pages and did the same thing in my code but this is giving me the expection.
Can anyone please help me? How to resolve this exception? and Why this exception is coming?
main.dart file
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp>{
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Please select your language',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold
),
),
const Text (
'You can change the language at any time',
style: TextStyle(
fontSize: 16,
color: Color.fromRGBO(106, 108, 123, 100)
),
),
DropdownButton<String>(
items: <String>['English', 'Hindi', 'Marathi', 'Punjabi'].map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
value: 'English',
),
ElevatedButton(
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MobileNumber()//Exception on this line.
)
);
},
child: const Text("NEXT"),
)
],
),
)
)
);
}
}
MobileNumber.dart
import 'package:flutter/material.dart';
class MobileNumber extends StatelessWidget{
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Text("Mobile Number Page"),
),
);
}
}
Exception Stack
======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
Navigator operation requested with a context that does not include a Navigator.
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
When the exception was thrown, this was the stack:
#0 Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.dart:2554:9)
#1 Navigator.of (package:flutter/src/widgets/navigator.dart:2561:6)
#2 Navigator.push (package:flutter/src/widgets/navigator.dart:2019:22)
#3 MyAppState.build.<anonymous closure> (package:liveasy_task_flutter/main.dart:52:33)
#4 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1072:21)
#5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:253:24)
#6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:627:11)
#7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:306:5)
#8 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:239:7)
#9 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:615:9)
#10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#11 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#12 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#13 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#14 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#15 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:460:19)
#16 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:440:22)
#17 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:337:11)
#18 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:395:7)
#19 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:357:5)
#20 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:314:7)
#21 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:295:7)
#22 _invoke1 (dart:ui/hooks.dart:167:13)
#23 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:341:7)
#24 _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31)
Handler: "onTap"
Recognizer: TapGestureRecognizer#1dfff
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(183.0, 459.8)
finalLocalPosition: Offset(32.0, 18.0)
button: 1
sent tap down
CodePudding user response:
In your code the MaterialApp
uses aNavigator
widget internally, so that's good. But the thing is that the context
that you use is defined above it. Meaning that that context doesn't have a Navigator
. An easy solution that might be unintuitive to beginners is to move the MaterialApp
to outside the widget, like this:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp>{
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Please select your language',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold
),
),
const Text (
'You can change the language at any time',
style: TextStyle(
fontSize: 16,
color: Color.fromRGBO(106, 108, 123, 100)
),
),
DropdownButton<String>(
items: <String>['English', 'Hindi', 'Marathi', 'Punjabi'].map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
value: 'English',
),
ElevatedButton(
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MobileNumber()//Exception on this line.
)
);
},
child: const Text("NEXT"),
)
],
),
)
);
}
}
This way, the context
in the build
method of MyAppState
does have an ancestor that is a Navigator
widget.
CodePudding user response:
It looks like the error is occurring when you are trying to navigate to the MobileNumber page using the Navigator.push method. The error message states that the context you are using to push or pop routes from the Navigator does not include a Navigator.
To fix this error, you will need to wrap the MaterialApp widget in your main.dart file with a Navigator widget. This will allow you to use the Navigator to push and pop routes within the app.
Here's how you can modify your main.dart file to include a Navigator
widget:**strong text**
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp>{
@override
Widget build(BuildContext context) {
return Navigator(
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Please select your language',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold
),
),
const Text (
'You can change the language at any time',
style: TextStyle(
fontSize: 16,
color: Color.fromRGBO(106, 108, 123, 100)
),
),
DropdownButton<String>(
items: <String>['English', 'Hindi', 'Marathi', 'Punjabi']. map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
value: 'English',
),
ElevatedButton(
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MobileNumber()
)
);
},
child: const Text("NEXT"),
)
],
),
)
);
},
);
},
);
}
}
With this change, the Navigator widget will be able to manage the routes within your app and you should no longer see the error when trying to navigate to the MobileNumber page.
CodePudding user response:
look at the widgets in Flutter as a tree, with the context pointing to whichever node is being built with the build function. In your case, you have,
MainScreen <------ the context
--> MaterialApp
(--> Navigator built within MaterialApp)
--> Scaffold
--> body
--> Center
--> ElevatedButton
So when you are using the context to find the Navigator, you're using a context for the main screen which isn't under the navigator.
You can make a new Stateless or Stateful Widget to contain your Center and ElevatedButton, as the build function within those will point at that level instead, or you can use a Builder and define the builder callback (which has a context pointing at the Builder) to return the Center ElevatedButton.