Refresh listView from PopUntil - flutter

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),
),
);
}
}

Related

The return type '_MainPage' isn't a 'Widget', as required by the closure's context

I create page with bottom_nav_bar, but now i cant open it in emulator, bcs error Error: A value of type '_MainPage' can't be assigned to a variable of type 'Widget'.
Problem here: '/Main': (BuildContext context) => _MainPage(),
Here code:
import 'package:flutter/material.dart';
class LogInPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Log In")),
body: Center(
child: Row(
children: <Widget>[
RaisedButton(
onPressed: () {
Navigator.pushNamed(context, '/Main');
},
child: Text("Log In")),
RaisedButton(
onPressed: () {
Navigator.pushNamed(context, '/LogIn/Registr');
},
child: Text("Registration")),
],
)),
);
}
}
class QRCodePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("QR Scan")),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pushNamed(context, '/Main');
},
child: Text("Scan")),
));
}
}
class RegistrPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Registration")),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pushNamed(context, '/Main');
},
child: Text("Log In")),
));
}
}
class MyApp extends StatefulWidget {
#override
_MainPage createState() => _MainPage();
}
class _MainPage extends State<MyApp> {
int _currentIndex = 0;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text("Main")),
body: Container(),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home), backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.qr_code), backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.restaurant_menu), backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_basket), backgroundColor: Colors.blue),
],
onTap: (index){
setState(() {
_currentIndex = index;
});
},
),
);
}
}
void main()
{
runApp(MaterialApp(
initialRoute: '/LogIn',
routes: {
'/LogIn': (BuildContext context) => LogInPage(),
'/QRScan': (BuildContext context) => QRCodePage(),
'/LogIn/Registr': (BuildContext context) => RegistrPage(),
'/Main': (BuildContext context) => _MainPage(),
},
));
}
Shouldn't it be MyApp instead of _MainPage? _MainPage is not the Widget but the State.
void main() {
runApp(MaterialApp(
initialRoute: '/Main',
routes: {
'/LogIn': (BuildContext context) => LogInPage(),
'/QRScan': (BuildContext context) => QRCodePage(),
'/LogIn/Registr': (BuildContext context) => RegistrPage(),
'/Main': (BuildContext context) => MyApp(),
},
));
}
You should probably rename MyApp into MainPage for more clarity.
Also, you have to define the label or title of each BottomNavigationBarItem:
items: [
BottomNavigationBarItem(
label: 'Home',
icon: Icon(Icons.home),
backgroundColor: Colors.blue
),
...
],

Why do we need to push the context of our previous screen in flutter?

Why do we need to push the context of our previous screen in flutter?
Would we need this in order to keep track of the previous branch of the tree?
Why this is not working? I want to know the reason why this code is not working.
import 'package:flutter/material.dart';
void main() {
runApp(
FirstRoute(),
);
}
class FirstRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Navigation Basics',
home: Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
color: Colors.amberAccent,
child: Text('Open route'),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}),
);
},
),
),
),
);
}
}
You just need to break up your BuildContext into separate classes. And it's always good practice to split up different pages into different classes anyways. But not just different classes but an entirely different file.
import 'package:flutter/material.dart';
void main() {
runApp(
FirstRoute(),
);
}
class FirstRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Navigation Basics',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
color: Colors.amberAccent,
child: Text('Open route'),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (childContext) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}),
);
},
),
),
);
}
}

Flutter navigator not working : OnPress not showing second screen

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.

Flutter navigation

Can someone explain why not printing efeioi when it is back from pageE?
Page A
Navigator.pushNamed(context, PageB.ROUTE).then((onValue) {
print("efeioi");
});
Page B
Navigator.of(context)
.pushReplacementNamed(PageC.ROUTE, arguments: onValue);
PageC
Navigator.pushNamed(context, PageD.ROUTE,
arguments: onValue);
PageD
Navigator.pop(context); // back to Page C
Page C
Navigator.pushNamed(context, PageE.ROUTE,
arguments: onValue);
Page E
Navigator.of(context).popUntil(ModalRoute.withName(PageA.ROUTE));
I can't use Navigator.pop in Page E because it will back to Page C!
I have uploaded full code here
https://github.com/tony123S/navigation
As per your requirement I have implemented as below
main.dart
initState : this will be called when you navigate from E to A
refreshPage : it will not called as you already popped before returning to A Page
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,
),
home: A(),
routes: <String, WidgetBuilder>{
'/A': (BuildContext context) => new A(),
'/B': (BuildContext context) => new B(),
'/C': (BuildContext context) => new C(),
'/D': (BuildContext context) => new D(),
'/E': (BuildContext context) => new E(),
},
);
}
}
class A extends StatefulWidget {
#override
_FirstRouteState createState() => _FirstRouteState();
}
class _FirstRouteState extends State<A> {
final String fromPage;
_FirstRouteState({Key key, #required this.fromPage});
#override
void initState() {
// TODO: implement initState
super.initState();
print("Called askdfjaksdfj");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page A'),
),
body: Center(
child: RaisedButton(
child: Text('Open B'),
onPressed: () {
// Navigate to second route when tapped.
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => B()),
// );
Navigator.push(
context,
MaterialPageRoute(builder: (context) => B()),
).then((res) => refreshPage());
},
),
),
);
}
refreshPage() {
print("refresh page is called");
}
}
class B extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("B Page"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.of(context).pushNamed(
"/C",
);
},
child: Text('Go to C'),
),
),
);
}
}
class C extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("C Page"),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.pushNamed(
context,
"/D",
);
},
child: Text('Go to D'),
),
RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.pushNamed(
context,
"/E",
);
},
child: Text('Go to E'),
),
],
),
),
);
}
}
class D extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("D Page"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.pop(context);
},
child: Text('Go back to C'),
),
),
);
}
}
class E extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("E Page"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigator.pop(context);
// Navigator.of(context).pushNamed("/A");
// Navigator.of(context).popUntil(ModalRoute.withName('/A'));
Navigator.of(context)
.pushNamedAndRemoveUntil('/A', (Route<dynamic> route) => false,);
},
child: Text('Go to A'),
),
),
);
}
}
Please run code for better understanding and reply if you found any difficulty

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!'),
),
),
);
}
}