WillPopScope does not work for me, flutter - flutter

I have 4 different items in my bottom navigation menu and in one case I need to navigate to one page and delete all the pages in my stack so that I use this code to navigate my another screen;
Navigator.pushAndRemoveUntil(
context,
PageRouteBuilder(
pageBuilder: (context, anim1, anim2) => AnamenuTemelSayfa(currentIndex: 2),
transitionsBuilder: (context, anim1, anim2, child) => Container(child: child),
transitionDuration: Duration(milliseconds: 200),
),
(_) => true,
);
After this navigation when I hit the back button on the physical device it backs to the last screen that I've just came, to handle with this problem I change true value into false but when I do it after this navigation event in any pages of the app on the physical device back button does not work so that I try to do another thing is that to wrap second page with WillPopScope not to go back I've defined this code;
//Second page
onWillPop: () async {
return await Future.value(false);
},

if you want use willpopscope you should use Navigator.push instead of Navigator.pushAndRemoveUntil
pushAndRemoveUntil remove all pages until your current page then you cant go back to previous page and your WillPopScope not calling, so if you want prevent user to back to previous page you should wrap your scaffold with WillPopScope widget like this:
WillPopScope(
onWillPop: () async => false,
child: Scaffold(
// your code here
)
)
EDIT:
use this navigator (it`s remove all page until YourNewPage)
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context){
return YourNewPage();
}), (Route<dynamic> route) => false);

Your route predicate should return false to remove all the previous page and push new page.
Navigator.pushAndRemoveUntil(
context,
PageRouteBuilder(
pageBuilder: (context, anim1, anim2) => AnamenuTemelSayfa(currentIndex: 2),
transitionsBuilder: (context, anim1, anim2, child) => Container(child: child),
transitionDuration: Duration(milliseconds: 200),
),
(_) => false, // routePredicate
);
And now you don't need to use WillPopScope.

Related

Flutter PageTransitionSwitcher is not working

I want to add an animation when transitioning from user's profile page to the previous page. so I used PageTransitionSwitcher as already I'm using animations package for another purpose in the app.This is how I implemented it inside the back button of the page.When I click on back button it is not working.
onPress: () => {
PageTransitionSwitcher(
transitionBuilder: (child, animation, secondaryAnimation) =>
SharedAxisTransition(animation: animation, secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.horizontal),
child: NewMainTabs(),
)
},
you can use this function to build the route.
import 'package:animations/animations.dart';
import 'package:flutter/material.dart';
Route buildSharedZAxisTransitionPageRoute(Widget Function(BuildContext) builder,{RouteSettings? settings}) {
return PageRouteBuilder(
settings: settings,
pageBuilder: (context, animation, secondaryAnimation) => builder(context),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return SharedAxisTransition(
fillColor: Theme.of(context).cardColor,
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.scaled,
child: child,
);
});
}
Then you can call upper function to create your route and push it into navigator or just rebuild with another widget
Widget build(BuildContext context) {
return PageTransitionSwitcher(
transitionBuilder: (
Widget child,
Animation<double> primaryAnimation,
Animation<double> secondaryAnimation,
) {
return FadeThroughTransition(
child: child,
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
);
},
child: MyWidget(),
);
or
Navigator.of(context, rootNavigator: true).push(
buildSharedZAxisTransitionPageRoute(
(_) => const MyWidget())

Bloclistener Causing ambiguity in flutter

I have 9 screens where I am using fields to fill form from user inputs. I am using bloc for state management. The problem is with the navigation. I am using navigation with bloc listener. When i move from screen 1 to 2 and move back everything is ok.
from screen 2 to 3 and back everything is ok.
from screen 3 to 4 Navigation is ok but when I click for back many navigation screens pop up like screen 2 two times when i press back button 2 times then screen 3 pop up and then screen 1 pop up with back button.
and this behavior continue so forth until I reached last screen and remove all previous screens. my app also become very slow when i navigate with bloc listener. I dont know what is this behaviour.
Screen 1 bloc.
BlocListener<JobBloc, JobState>(
listener: (context, state) {
if (state is JobSuccessfulState)
widget.edit == true
? Navigator.pushAndRemoveUntil<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) =>
JobPostScreen8(state.data),
),
(route) =>
false, //if you want to disable back feature set to false
)
: Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => JobPostScreen2()));
},
Screen 2
BlocListener<JobBloc, JobState>(
listener: (context, state) {
if (state is JobSuccessfulState)
widget.edit == true
? Navigator.pushAndRemoveUntil<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) =>
JobPostScreen8(state.data),
),
(route) =>
false, //if you want to disable back feature set to false
)
: Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => JobPostScreen3()));
},
Screen 3
BlocListener<JobBloc, JobState>(
listener: (context, state) {
if (state is JobSuccessfulState)
widget.edit == true
? Navigator.pushAndRemoveUntil<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) =>
JobPostScreen8(state.data),
),
(route) =>
false, //if you want to disable back feature set to false
)
: Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => JobPostScreen4()));
},
...
and it is all same upto screen 7. Screen 7
BlocListener<JobBloc, JobState>(
listener: (context, state) {
if (state is JobSuccessfulState)
Navigator.pushAndRemoveUntil<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) => JobPostScreen8(state.data),
),
(route) =>
false, //if you want to disable back feature set to false
);
},
with this all navigation stack is removed and my application run smoothly. Please suggest me what is better approch in navigation with bloc.

pushReplacement or pushAndRemoveUntil(Route<dynamic> route) => false not Working

A page-based route cannot be completed using imperative api, provide a new list without the corresponding Page to Navigator.pages instead.
'package:flutter/src/widgets/navigator.dart':
Failed assertion: line 3075 pos 7: '!hasPage || isWaitingForExitingDecision'
Only Navigator.push works. Before Flutter 2 it was working.
Navigator.pushAndRemoveUntil(
context,
PageRouteBuilder(
transitionDuration: const Duration(milliseconds: 3300),
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return _CustomPageTransition(
routeAnimation: animation,
fullscreenDialog: false,
child: child);
},
pageBuilder: (_, __, ___) => LoginScreen(),
),
(route) {
print(route.settings.name);
return false;
});
It's an old question that nowaday I solved it by using auto_route package. But I think if you use Navigator.replace it will work.
AutoRouter.of(context).replaceNamed(LoginScreenRoute().path);
Or
AutoRouter.of(context).replace(LoginScreenRoute());
In the MaterialAutoRouter:
#MaterialAutoRouter(routes: <AutoRoute>[
AutoRoute(page: RouteAuthentication, initial: true),
CustomRoute(
page: LoginScreen,
fullscreenDialog: true,
transitionsBuilder: TransitionsBuilders.slideLeftWithFade,durationInMilliseconds: 3300
),])
In my case I wanted to animate with the Hero widget. But the code below doesn't work.
AutoRouter.of(context).pushAndPopUntil(LoginScreenRoute(),
predicate: (_) => false);

Flutter: How do I pop dialog as well as current page?

Below is the code.
Navigation to Login page, from Home page
ElevatedButton(
onPressed: () => Navigator.of(context, rootNavigator: true)
.push(MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => UserLoginPage(),
)),
child: Text('Login to continue'),
),
Inside Login page:
BlocConsumer<UserAuthCubit, UserAuthState>(
listener: (context, state) {
if (state is UserAuthorized) {
Navigator.of(context, rootNavigator: true).pop();
}
if (state is UserAuthWaiting) {
showModalBottomSheet(
useRootNavigator: true,
isDismissible: false,
context: context,
builder: (context) {
return WillPopScope(
onWillPop: () async => false,
child: Center(
child: Text(state.msg),
),
);
});
dialog = true;
} else {
if (dialog) {
Navigator.of(context, rootNavigator: true).pop();
dialog = false;
}
}
},
builder: (context, state) { // some widget code... }
When the state is UserAuthorized, I want to pop the dialog as well as the LoginPage, so as to return to the last page i.e. Home page. However, with the code above, sometimes, it works, and on another time, the Home page is also popped out.
I tried, with/without rootNavigator set to true, but couldn't achieve my objective.
Please help me understand what I'm missing here.
I have checked the answer here How to dismiss flutter dialog?
.
You can simply use
Navigator.popUntil(context, (route) {
return count++ == 2;
});
UPDATE:
If you don't know how many page you should pop then you should use
Navigator.push(context, MaterialPageRoute(builder: (context)=>YourMaterialClassName(), settings: RouteSettings(name: "nameOfYourClass")));
while you push your material class.
then in the time of poping up use
Navigator.popUntil(context, (route) => route.settings.name == "nameOfYourClass");
I suggest after the dialog return true, instead of using Navigator.of(context).pop().
Or you can try using
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => HomePage()),
)
By doing so you replace the LoginPage with HomePage.

Is there a method to switch from one page to another?

I'm developing an application using flutter, I got to display the first page and I created sub pages.
My problem is that I don't know how to display a second page when you click on an item. example: I created a grid of 8 boxes and each box must display a unique page at the click. i.e. item 1 returns page 1, item 2 returns page 2, item 3 returns page 3... etc.
here is a capture of the first page
You can achieve this with the following code example. With the Navigator you can go to the next page and display it.
class NavigatorPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: GridView.builder(
itemCount: 4,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () => nextPage(context, index),
child: Card(
...
),
);
},
),
),
);
}
void nextPage(BuildContext context, int index) {
if (index == 0) {
Navigator.push(context, MaterialPageRoute(builder: (context) => Page1()));
} else if (index == 1) {
Navigator.push(context, MaterialPageRoute(builder: (context) => Page2()));
}
...
}
}
what you need is the Navigator object. In flutter it's used to navigate the user between screens by having one initial screen and then stacking more on top of it. This is a good tutorial on the basics.
In general good practise is to use named routes (tutorial here) but you don't need to use named routes to use the Navigator. In your example you can put the following in a onPressed argument on each item:
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return PageTwo()
);
},
);
On first Screen, write this code.
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return SecondScreen()
);
},
);
You must import the Second Screen in First Screen dart file.