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

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

Related

Set default transition for go_router in Flutter

as the docs from go_router describe, it is easy to set pageBuilder-Transitions for single pages.
However, I want to set the default PageTransition for all pages.
How do I set the default page transition with/for go_router in Flutter?
Single Page:
// this is the proposed method to do it for single pages
// how can i apply it to all pages without writing the same code?
GoRoute(
path: '/login',
builder: (context, state) => const LoginScreen(),
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
child: const LoginScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
),
),
Best regards
The go_router package does not support this at the moment, but to reduce code duplication, you can create a helper function that would apply the custom transition for your route, like:
CustomTransitionPage buildPageWithDefaultTransition<T>({
required BuildContext context,
required GoRouterState state,
required Widget child,
}) {
return CustomTransitionPage<T>(
key: state.pageKey,
child: child,
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
);
}
<...>
GoRoute(
path: '/login',
builder: (context, state) => const LoginScreen(),
pageBuilder: (context, state) => buildPageWithDefaultTransition<void>(
context: context,
state: state,
child: LoginScreen(),
),
),
The more correct way is inheritance from CustomTransitionPage.
class WebPage extends CustomTransitionPage {
WebPage({
LocalKey key,
... // other properties taken from `MaterialPage`
required Widget child
}) : super(
key: key,
transitionBuilder: (...) {
return FadeTransition(...);
}
child: child, // Here you may also wrap this child with some common designed widget
);
}
Then
GoRoute(
path: '/login',
pageBuilder: (context, state) => WebPage(
key: state.pageKey,
child: const LoginScreen(),
),
),

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())

How to use PageTransitionsBuilder when navigating to a different screen?

final builder = OpenUpwardsPageTransitionsBuilder();
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (_, __, ___) => Page2(),
transitionsBuilder: builder, // error
),
);
What I understand is, I can only setup PageTransitionsBuilder inside a Theme, is there any way to use it inside Navigator?
The most simple solution is a custom PageRouteBuilder:
class MyPageRouteBuilder<T> extends PageRouteBuilder<T> {
final PageTransitionsBuilder pageTransitionsBuilder;
MyPageRouteBuilder({
#required RoutePageBuilder pageBuilder,
#required this.pageTransitionsBuilder,
}) : assert(pageTransitionsBuilder != null), super(pageBuilder: pageBuilder);
#override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return pageTransitionsBuilder.buildTransitions(this, context, animation, secondaryAnimation, child);
}
}
Here only pageBuilder is passed to super() but you can add any named parameter that PageRouteBuilder accepts (like transitionDuration for example)
Now, you can use it with:
Navigator.of(context).push(
MyPageRouteBuilder(
pageBuilder: (ctx, a1, a2) => Page2(),
pageTransitionsBuilder: OpenUpwardsPageTransitionsBuilder(),
)
);
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (ctx, a1, a2) => Screen2(),
transitionsBuilder: (ctx, anim, a2, child) => FadeTransition(opacity: anim, child: child),
transitionDuration: Duration(milliseconds: 3000),
),
);
You can vary milliseconds time, as per your need in-app.

Flutter set transitions for custom routes

in our application we implementing custom route navigation and i want to set transition for that, for example, this is our custom route which that work fine without any problem
Navigator(
key: navigatorKey,
initialRoute: Page.screenDashboard.route,
onGenerateRoute: (settings) {
final pageName = settings.name;
final page = _fragments.keys.firstWhere(
(element) => describeEnum(element) == pageName);
return MaterialPageRoute(
builder: (context) => FadeAndSlideRightTransition(page: _fragments[page]));
},
),
in that how can i set transition for MaterialPageRoute?
for example:
class SlideRightRoute extends PageRouteBuilder {
final Widget page;
SlideRightRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
SlideTransition(
position: Tween<Offset>(
begin: const Offset(-1, 0),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
this test doesn't work and i get error:
return MaterialPageRoute(builder: (context) => SlideRightRoute (page: _fragments[page]));
error
error: The return type 'SlideRightRoute ' isn't a 'Widget', as required by the closure's context. (return_of_invalid_type_from_closure at [fluttersamples] lib\screens.dart:62)
using
return SlideRightRoute(page: _fragments[page]);
instead of
return MaterialPageRoute(builder: (context) => _fragments[page]);
solved my issue

WillPopScope does not work for me, 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.