How to use PageTransitionsBuilder when navigating to a different screen? - flutter

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.

Related

Flutter push screen with pop animation

i have the code below and what i would like to achieve is to have an animation transition like 'pop' when calling 'push'. the code that i have just slides the new page from the direction that i specify. i would like to have the old screen be the one that is moving instead.
import 'package:flutter/material.dart';
class CustomPageRoute extends PageRouteBuilder {
final Widget child;
final AxisDirection direction;
CustomPageRoute({
required this.child,
required this.direction,
}) : super(
transitionDuration: const Duration(milliseconds: 200),
reverseTransitionDuration: const Duration(milliseconds: 200),
pageBuilder: (context, animation, secondaryAnimation) => child,
);
#override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) =>
SlideTransition(
position: Tween<Offset>(begin: getBeginOffset(), end: Offset.zero)
.animate(animation),
child: child,
);
Offset getBeginOffset() {
switch (direction) {
case AxisDirection.up:
return const Offset(0, 1);
case AxisDirection.down:
return const Offset(0, -1);
case AxisDirection.right:
return const Offset(-1, 0);
case AxisDirection.left:
return const Offset(1, 0);
}
}
}
You can use pageRouteBuilder with zero duration
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, _, __) => NewPage(),
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
),
);
Edit
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, _, __) => Page2(),
transitionsBuilder: (context, anim, a2, child) => FadeTransition(opacity: anim, child: child),
transitionDuration: Duration(milliseconds: 2000),
),
);
for anyone looking to achieve the same thing, it can be achieved by using popUntil

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

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