Reputation:
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
Upvotes: 1
Views: 522
Reputation: 23164
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.
Upvotes: 1
Reputation: 787
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.
Upvotes: 0