Unusual page transition animation in Flutter, what can be a reason? - flutter

My android flutter app started makes strange page animation when moving to next page and back. I'm not shure what I could change to make that happen. In other words, it does not the way as android app do by default. Not special animation or so was used. Just usual way to go to the next page:
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const HomeView()),
);
or
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const About()),
);
Now, when you go to a new page, its content appears as if from the center of the screen. And when you click on the back button - the page appears, as it were, from the edges to the center.

The default page transition animation was changed in Flutter 3.0. The default FadeUpwardsPageTransitionsBuilder was replaced with ZoomPageTransitionsBuilder, which is what I believe you are referring to as "From the center of the screen" and "From the edges to the center".
If you want to revert back to the old animation use the below code
MaterialApp(
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: Map<TargetPlatform, PageTransitionsBuilder>.fromIterable(
TargetPlatform.values,
value: (dynamic _) => const FadeUpwardsPageTransitionsBuilder(), //applying old animation
),
),
),
)
Know more about this change in the flutter dev docs.

Related

How to switch the screen smoothly?

I have three screens: 1, 2, and 3.
I want to switch from screen 2 to screen 3, but when I pop screen 2 and push screen 3, then it shows screen 1 for a while, then it shows screen 3, so is there any way to switch screens using pop after push or not?
this code not expectations
Navigator.push(
context,
MaterialPageRoute<Widget>(
builder: (context) => widget,
),
);
Navigator.pop(context);
Using pushReplacement insted of push
Navigator.pushReplacement(
context,
MaterialPageRoute<Widget>(
builder: (context) => widget,
),
);
Using pushReplacement insted of push
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => widget,
),
);
The behavior you're describing is likely because when you call Navigator.pop(context), it removes the current screen (screen 2) from the navigation stack, but the framework hasn't yet had a chance to build and display the new screen (screen 3) that you pushed. So, for a brief moment, the previous screen (screen 1) is visible.
One way to switch screens without that flicker is to use Navigator.pushReplacement instead of Navigator.push followed by Navigator.pop. Navigator.pushReplacement removes the current screen from the navigation stack and replaces it with the new screen, all in one step.
Example:
Navigator.pushReplacement(
context,
MaterialPageRoute<Widget>(
builder: (context) => widget3,
),
);
This will directly switch from screen 2 to screen 3.
It is generally not recommended to use both Navigator.push() and Navigator.pop() together in the same function call, as this can cause unexpected behavior. Instead, you can use Navigator.replace() to replace the current screen with a new one, or use Navigator.pushNamedAndRemoveUntil() to push a new screen and remove all the screens that come before it.

NavigationRail with go_router

I'm developing a web/desktop application that has a fairly standard UI layout involving a NavigationRail on the left and a content pane taking up the remainder of the screen.
I've reciently added go_router so I can properly support URLs in web browsers, however in doing so I have lost the ability to have any form of transition/animation when moving between pages as calling context.go() causes a hard cut to the next page.
Theres also the issue that go_router routes have to return the full page to be rendered meaning I need to include the navigation rail on every page rather than each page being just the content relevant to that page. I believe this is also the main reason all animations are broken, because clicking a link effectively destroys the current navigation rail and builds a new one for the new page
I couldn't see anything in go_router but is there any form of builder API available that can output and refresh a single section of the page? I'm thinking of something like bloc's BlocBuilder which listens for state changes and rebuilds just the widget its responsible for when a change occures.
Alternatively, is there a way to update the current URL without rebuilding the whole page?
Or is go_router just not capable of what I'm after, and if so, are there any alternatives that can do this?
The overall effecti I'm after is similar to the material site https://m3.material.io/develop
Clicking around the various buttons feels like you are navigating around within an app rather than clicking on links and loading new pages
Thanks for your help
I solved this with a Shell Route. I got the idea when going through the go_router 5 migration guide. I saw that they had a navigatorBuilder property in which they were wrapping every route in a Scaffold with AppBar. And it said to migrate:
Before migration:
final GoRouter router = GoRouter(
routes: <GoRoute> [
GoRoute(
path: '/',
builder: (_, __) => const Text('/'),
),
GoRoute(
path: '/a',
builder: (_, __) => const Text('/a'),
)
],
navigatorBuilder: (BuildContext context, GoRouterState state, Widget child) {
return Scaffold(
appBar: AppBar(title: Text(state.location)),
body: child,
);
}
);
After Migration:
final GoRouter router = GoRouter(
routes: <GoRoute> [
ShellRoute(
builder: (_, GoRouterState state, child) {
return Scaffold(
body: child,
appBar: AppBar(title: Text(state.location)),
);
},
routes: [
GoRoute(
path: 'a',
builder: (_, __) => const Text('a'),
),
GoRoute(
path: 'b',
builder: (_, __) => const Text('b'),
)
],
),
],
);
Now every route in the ShellRoute.routes property will be wrapped with that Scaffold and AppBar, it will not rebuild upon navigation, so will behave as a persistent AppBar, NavigationBar, or whatever should. Now it shows the page transition animations when you do context.go('some_route') (for example from a NavigationBar in the ShellRoute). You also don't run into the issue Felix ZY was having, accessing GoRouter from the context.

How to solve Swipe back not working on iOS

each time i use a plugin to move to the next page on iOS the swipe back will not work like
Navigator.push(
context,
Transition(
child: Bio(),
transitionEffect: TransitionEffect.BOTTOM_TO_TOP),
);
i have use like 5 plugin now swipe back is not working
but if i use this
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (ctx) => Actitvities(),
),
);
the swipe back works....
but i want to use transition for the page route
in my case.
i was using a plugin and the plugin is using
WillPopScope (
onWillPop: () async {
},
so i fork the plugin and remove the willpopscope.
then i add the fork plugin like this to my pubspeck
kittens:
git:
url: git://github.com/munificent/kittens.git
ref: some-branch
full example here

Navigation in Flutter App - does not work as intended

I try to build a flutter app and want to navigate trough the pages.
I build a drawer with a menu with several items to open new pages - that works fine.
onTap: () {
Navigator.of(context).pop();
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) => new Page1(),
),
);
},
By pressing on the Page1 menuitem page1 opens fine.
Inside page1 I have a slidable list with "edit" and "details". I open this with
onTap: () {
Navigator.of(context).pop();
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => new DetailsPage(),
),
);
},
In the details Page I see all the things i wanna see, but when I press the Back button in the appBar i am back at home screen with closed drawer.
I tried to put onPressed: () => Navigator.pop(context); inside the appBar section but this doesn´t work either.
Now I got what I want by using always Navigator.push but I am sure that this is not right, so that navigator stack gets bigger and bigger.
What I do wrong? Why .pop does not bring me to the last page?
Any ideas?
Thx in advance
Patrick
Just remove the line with the Navigator.of(context).pop();in the Page1 onTap.
you can use pushReplacement in any cases you need to remove current page from stack and route to new page.
Replace the current route of the navigator that most tightly encloses
the given context by pushing the given route and then disposing the
previous route once the new route has finished animating in.
here is the documentation

How to restore last route in Flutter

I'm developing a Flutter app and I have a problem.
In my main.dart I set a home route that is "FirstScreen", then the user can go to the LoginScreen to sign into the account. So if I press the home button and then I try to re-open the app the screen that appear is FirstScreen, so how can I show the last route the user have seen?
I've searched on Flutter docs and on other question in StackOverflow for some solutions but I found nothing that work for me.
This is my main.dart build.
Widget build(BuildContext context) {
return MaterialApp(
home: FirstScreen(),
routes: {
'/screen1' : (context) => Screen1(),
'/homeScreen' : (context) => HomeScreen(navigatorKey: navigatorKey,),
'/registerScreen' : (context) => RegisterScreen(),
'/screen2' : (context) => Screen2(),
'/firstScreen' : (context) => FirstScreen(),
'/userProfileScreen' : (context) => UserProfileScreen(),
},
navigatorKey: navigatorKey,
);
You'll need to keep track of the latest route the user has visited and store that somewhere persistent so that it survives app restarts. Perhaps look at the shared preferences package as a simple approach:
https://pub.dev/packages/shared_preferences
When the app starts, look in shared preferences to see if you have the previous route stored, and navigate to it (or set it as the home route). If not, fall back to the FirstScreen as a default.
I've find a solution, using WidgetBindingObserver, and put this line : WidgetsBinding.instance.addObserver(this); inside every StatefulWidget initState.