Flutter navigator not working : OnPress not showing second screen - flutter

This is my code don't know why its not moving to screen 2 on button press:
Am beginner in dart/flutter please help. On press of button it's not showing screen2
//main.dart
import 'package:flutter/material.dart';
import 'screen_1.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Screen1(),
);
}
}
//screen_1.dart
import 'package:flutter/material.dart';
import 'screen_2.dart';
class Screen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen 1'),
),
body: Container(
child: Center(
child: RaisedButton(
color: Colors.pink,
child: Text(
'Go to Screen 2',
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return Screen2();
},
),
);
},
),
),
),
);
}
}
//screen_2.dart
import 'package:flutter/material.dart';
class Screen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text('Screen 2'),
),
body: Center(
child: RaisedButton(
color: Colors.blue,
child: Text('Go Back To Screen 1'),
onPressed: () {},
),
),
);
}
}
onPressed of Screen1 class should show Screen2 but it's not happening.

I tried this and it does move to Screen2:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Screen1(),
);
}
}
//screen_1.dart
class Screen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen 1'),
),
body: Container(
child: Center(
child: RaisedButton(
color: Colors.pink,
child: Text(
'Go to Screen 2',
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return Screen2();
},
),
);
},
),
),
),
);
}
}
//screen_2.dart
class Screen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text('Screen 2'),
),
body: Center(
child: RaisedButton(
color: Colors.blue,
child: Text('Go Back To Screen 1'),
onPressed: () {},
),
),
);
}
}
This may be because StatelessWidget is part of material.dart yet you failed to import it in the first dart file.

Related

Flutter navigator hides (covers) first window conent

Why when I use the navigator to go to another page(widget) that covers just part of the screen, I can't see the first-page content (which is on top of the page)?
I tried code from this example (https://docs.flutter.dev/cookbook/navigation/navigation-basics) and modified it a little to show what I need:
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatelessWidget {
const FirstRoute({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First Route'),
),
body: Center(
child: ElevatedButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SecondRoute()),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
const SecondRoute({super.key});
#override
Widget build(BuildContext context) {
return Container(
padding:const EdgeInsets.only(top:128),
color:Colors.transparent,
child: Scaffold(
appBar: AppBar(
title: const Text('Second Route'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
),
);
}
}
You can achieve this using bottom sheet.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'example',
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
void _show(BuildContext ctx) {
showModalBottomSheet(
elevation: 10,
isScrollControlled: true,
context: ctx,
builder: (ctx) => Container(
//change height to change height of bottom sheet
height: MediaQuery.of(ctx).size.height * 0.75,
alignment: Alignment.center,
child: const Text('bottom sheet'),
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Example'),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
child: const Text('Show The BottomSheet'),
onPressed: () => _show(context),
),
),
),
);
}
}
use this class instead of your class
class SecondRoute extends StatelessWidget {
const SecondRoute({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Route'),
),
body: Container(
padding:const EdgeInsets.only(top:128),
child: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
),
);
}
}

My text widget not showing when I use MaterialPageRoute

Question
When I used MaterialPageRoute my Text Widget in page 2 isn't showing.
What I do here wrong?
My main page
class _MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(context,
new MaterialPageRoute(builder: (context) => Page2()));
},
),
body: Container(
child: Center(
child: Text(
'Page 1',
style: TextStyle(fontSize: 30.0),
)),
)));
}
}
Page2 (The message that I print "Moved to page 1" printed to the screen actually.
import 'package:flutter/material.dart';
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
var black = Colors.black;
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pop(context);
print("Moved to page 1");
},
),
backgroundColor: Colors.blue,
body: Container(
child: Center(
child: Text(
'Page 2',
style: TextStyle(
fontSize: 2.0,
),
),
),
));
}
}
Thanks
Try to remove the home body and put it inside a new class like this
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Page1());
}
}
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
print('a');
Navigator.push(context,
MaterialPageRoute(builder: (context) => Page2()));
},
),
body: Container(
child: Center(
child: Text(
'Page 1',
style: TextStyle(fontSize: 30.0),
)),
));
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
var black = Colors.black;
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pop(context);
print("Moved to page 1");
},
),
backgroundColor: Colors.blue,
body: Container(
child: Center(
child: Text(
'Page 2',
style: TextStyle(
fontSize: 2.0,
),
),
),
));
}
}
This is happening due to the context that you are passing to navigator.
For more info you can read this
Navigator operation requested with a context that does not include a Navigator

Refresh listView from PopUntil

Just wonder if I use this code to return PageA from PageD, which function will it get called in PageA?
PageD
Navigator.of(context).popUntil(ModalRoute.withName(PageA.ROUTE));
I would like to make the listView on PageA refreshed once it is back from PageD, but I don't know how to achieve it.
I added a then in PageA, but it is not printing anything.
Navigator.pushNamed(context, PageB.ROUTE).then((onValue) {
print("call from Page4");
_refreshListView();
});
Edit
My project flow is Page A > Page B > Page C > Page D > page A.
All you need to do is return data when you pop PageD and await the data when you push.
This code should help:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/',
routes: {
'/' : (context) => PageA(),
'/go': (context) => PageD()
},
);
}
}
class PageA extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page A"),
),
body: Center(
child: ListView(
children: <Widget>[
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_navigateAndDisplaySelection(context);
},
child: Icon(Icons.forward),
),
);
}
_navigateAndDisplaySelection(BuildContext context) async {
final result = await Navigator.pushNamed(
context,
'/go'
);
if(result){
print(result);
//call the refresh ListView here
_refreshListView();
}
}
}
class PageD extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page D"),
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white,),
onPressed: (){
Navigator.pop(context, true);
},
)
),
body: Center(
child: Text("Press back!!"),
),
);
}
}
As to what you explained in the comments... you have to pass arguments from Page D to A when navigating.
Hope this helps.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/',
routes: {
'/': (context) => PageA(),
'/b': (context) => PageB(),
'/c': (context) => PageC(),
'/d': (context) => PageD()
},
);
}
}
class PageA extends StatelessWidget {
#override
Widget build(BuildContext context) {
final bool shouldRefresh = ModalRoute.of(context).settings.arguments;
if (shouldRefresh != null) {
print(shouldRefresh);
//call the refresh ListView here
_refreshListView();
}
return Scaffold(
appBar: AppBar(
title: Text("Page A"),
),
body: Center(
child: ListView(
children: <Widget>[],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pushNamed(context, '/b');
},
child: Icon(Icons.forward),
),
);
}
}
class PageB extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page B"),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.forward),
onPressed: () {
Navigator.pushNamed(context, '/c');
},
),
);
}
}
class PageC extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page C"),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.forward),
onPressed: () {
Navigator.pushNamed(context, '/d');
},
),
);
}
}
class PageD extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Page D"),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: () {
Navigator.pushNamed(context, '/', arguments: true);
},
)),
body: Center(
child: Text("Press back!!"),
),
);
}
}
If you want to go to Page D when you press back in Page A then use this
class PageA extends StatelessWidget {
#override
Widget build(BuildContext context) {
final bool shouldRefresh = ModalRoute.of(context).settings.arguments;
print(shouldRefresh);
return Scaffold(
appBar: AppBar(
title: Text("Page A"),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: () {
Navigator.pushNamed(
context,
'/d',
arguments: true
);
},
),
),
body: Center(
child: ListView(
children: <Widget>[
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pushNamed(context, '/b');
},
child: Icon(Icons.forward),
),
);
}
}

Flutter navigation by route name in statefull widget

i am trying to go on another page using navigation, but i am getting error;
Navigator operation requested with a context that does not include a
Navigator.
i am just trying to move on next page, i followed flutter documentations for this stateless widget but how to do with state full widget.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State createState() => new MyApp1();
}
class MyApp1 extends State<MyApp> {
List<Widget> _listSection = [];
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Share IDEASS',
initialRoute: '/',
routes: {
'/second': (context) => SecondScreen(),
},
home: Scaffold(
appBar: AppBar(
title: Text('IDEAS'),
),
body: Container(
child: Stack(
children: [
floatingButton(),
],
),
),
),
);
}
Widget floatingButton() {
return Container(
padding: const EdgeInsets.all(30),
alignment: Alignment.bottomRight,
child: FloatingActionButton(
onPressed: () {
Navigator.pushNamed(context, "/SecondScreen");
},
child: Text("+"),
backgroundColor: Colors.blue,
),
);
}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
You should use the named route you created.
Widget floatingButton(BuildContext context) { // added context as a parameter
return Container(
padding: const EdgeInsets.all(30),
alignment: Alignment.bottomRight,
child: FloatingActionButton(
onPressed: () {
Navigator.pushNamed(context, "/second"); // Changed this to use the named route
},
child: Text("+"),
backgroundColor: Colors.blue,
),
);
}
}
then use the following
body: Container(
child: Stack(
children: [
floatingButton(context),
],
),
),
The situation here is that the floatingButton() uses a context with the navigator to push the given page route. But the context used is provided in the parent Widget(MaterialApp) it self, which doesn't include a Navigator, hence the error.
So, Try this approach:
Separate the Home widget from the MaterialApp, like below:
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Share IDEASS',
initialRoute: '/',
routes: {
'/second': (context) => SecondScreen(),
},
home: HomePage(),
);
Create a stateless widget containing the Scaffold:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('IDEAS'),
),
body: Container(
child: Stack(
children: [
floatingButton(),
],
),
),
);
}
}
Hope it helps. Let me know if this doesn't work.
You have made two mistakes because of which your code is not working:
You have used wrong route name. Replace /SecondScreen with /second
You have used wrong context. You can get Navigator only if your widget has MaterialApp as it's parent and here you are using context of MyApp1 so it is not working.
Following is a working code for your reference.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State createState() => new MyApp1();
}
class MyApp1 extends State<MyApp> {
List<Widget> _listSection = [];
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Share IDEASS',
initialRoute: '/',
routes: {
'/second': (context) => SecondScreen(),
},
home: AppContent(),
);
}
}
class AppContent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('IDEAS'),
),
body: Container(
child: Stack(
children: [
floatingButton(context),
],
),
),
);
}
Widget floatingButton(BuildContext context) {
return Container(
padding: const EdgeInsets.all(30),
alignment: Alignment.bottomRight,
child: FloatingActionButton(
onPressed: () {
Navigator.pushNamed(context, "/second");
},
child: Text("+"),
backgroundColor: Colors.blue,
),
);
}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}

How to go from one screen to another clearing all the previous screens from stack?

In my Flutter project, I have three screens - Screen0, Screen1, Screen2. Now, from the screen0 , I can go to the screen1 with a button click, then from screen1 we can go to screen2 with a button. In screen2, I have a button which I have used to go back to screen0. As Screen0 is the initial screen, I want to clear all the previous screens when I come back to Screen0 and don't want to have any back option like in this image-
And here's my code-
main.dart
import 'package:flutter/material.dart';
import 'screen0.dart';
import 'screen1.dart';
import 'screen2.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context)=> Screen0(),
'/first': (context)=> Screen1(),
'/second': (context)=> Screen2(),
},
);
}
}
I have set all the routes in my main.dart file. Then in the Screen0, I have a button to go to screen1 like below-
screen0.dart
import 'package:flutter/material.dart';
class Screen0 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: Text('Screen 0'),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
color: Colors.red,
child: Text('Go to screen 1'),
onPressed: (){
Navigator.pushNamed(context, '/first');
},
),
],
),
),
);
}
}
In the screen1, I have a button to go to screen2-
class Screen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: Text('Screen 1'),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
color: Colors.red,
child: Text('Go to screen 2'),
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return Screen2();
})
);
},
),
],
),
),
);
}
}
Now, in the screen2, i have the button to go to screen0 -
class Screen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: Text('Screen 2'),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
color: Colors.red,
child: Text('Go to screen 0'),
onPressed: (){
Navigator.pop(context, Screen2);
Navigator.pushNamed(context, '/');
},
),
],
),
),
);
}
}
I have tried some solution like using Navigator.pushAndRemoveUntil given in the below link-
Flutter - Navigate to a new screen, and clear all the previous screens
But this solution didn't work for me.
So, it would be nice if someone help me out this code to solve the problem.
use pushNamedAndRemoveUntil
for example
Navigator.of(context).pushNamedAndRemoveUntil('/screen4', (Route<dynamic> route) => false);