Closed AscentionOne closed 2 years ago
To answer your second question, path is not mandatory for mobile apps.
Please see the bottom of this page: https://autoroute.vercel.app/basics/root_router
Got it. Thank you!
I have the same issue with Hero animations not showing.
@AscentionOne @WasserEsser It seems HeroController is maintained inside the MaterialApp now, it's creating a HeroControllerScope but for a reason I still don't know nested Navigators can not access that scope although it seems at the top of the widgets tree, p.s it seems that it's old known problem of Nested Navigators
anyways.. for now a decent fix would be wrapping the Nested Router with our own HeroController scope, you could make a general Hero-Scoped EmptyRouterPage like follows
class HeroEmptyRouterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return HeroControllerScope(
controller: HeroController(),
child: AutoRouter(),
);
}
}
p.s you could also pass the HeroController as a Navigator Observer to AutoRouter() instead of scoping it.
const booksTab = AutoRoute(
path: 'books',
// use it instead of EmptyRouterPage
page: HeroEmptyRouterPage,
name: 'BooksTab',
children: [
AutoRoute(path: '', page: BookListPage),
AutoRoute(path: ':id', page: BookDetailsPage),
],
);
if this turns out to be the best practice to do this, I'll handle it internally in future builds.
@Milad-Akarie Thank you for the answer! Yes, I also did some research that this stackoverflow issue also recommend that you can put the HeroController
in the observers
. There seems no observers
argument in the current AutoRouter
correct? I'll try your method and see how it goes! Thank you! π
@Milad-Akarie I try your method and it works! π
Another question is, let's say if I have Hero
widgets in multiple pages (ex: booksPage, userPage, moviesPage... etc) I have to wrap every route like what you did using HeroEmptyRouterPage
or I can just wrap the root route (ex: homePage) and all the relative page can get the HeroController
. Thank you.
@AscentionOne it's called NavigatorObservers because it passes it to the navigator it wraps
AutoRouter(navigatorObservers: [],)
@AscentionOne I haven't tested it like that but technically yes wrapping the root should be enough. maybe let me know if you get the chance to try it?
I think you should stick the scoping approach if you want this to work though.
@AscentionOne I haven't tested it like that but technically yes wrapping the root should be enough. maybe let me know if you get the chance to try it?
Okay, I will try it and let you know how it goes!
@AscentionOne it's called NavigatorObservers because it passes it to the navigator it wraps
AutoRouter(navigatorObservers: [],)
I saw it in AutoRouter
but I haven't seen one in MaterialAutoRouter
since I am using MaterialAutoRouter
.
@AscentionOne MaterialAutoRouter extends AutoRouterAnnotation, it's not the same as AutoRouter() the widget.
That's what I meant
class HeroEmptyRouterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AutoRouter(navigatorObservers: [HeroController()]);
}
}
@AscentionOne MaterialAutoRouter extends AutoRouterAnnotation, it's not the same as AutoRouter() the widget.
That's what I meant
class HeroEmptyRouterPage extends StatelessWidget { @override Widget build(BuildContext context) { return AutoRouter(navigatorObservers: [HeroController()]); } }
I understand now, thank you! Sorry for the brain delay π
@Milad-Akarie I also try wrapping the root widget with HeroControllerScope
which has multiple Hero
widgets in different pages. Apparently, it doesn't work. We have to wrap every pageRoute with their own HeroControllerScope
. I checked it work.
Below is the error message I got when I wrap the root route with HeroControllerScope
.
ββββββββ Exception caught by widget library ββββββββββββββββββββββββββββββββββββ
The following assertion was thrown:
A HeroController can not be shared by multiple Navigators. The Navigators that share the same HeroController are:
- NavigatorState#d4bef(tickers: tracking 1 ticker)
- NavigatorState#b3a7d(tickers: tracking 1 ticker)
Please create a HeroControllerScope for each Navigator or use a HeroControllerScope.none to prevent subtree from receiving a HeroController.
When the exception was thrown, this was the stack
#0 NavigatorState._updateHeroController.<anonymous closure>.<anonymous closure>
package:flutter/β¦/widgets/navigator.dart:3501
#1 SchedulerBinding._invokeFrameCallback
package:flutter/β¦/scheduler/binding.dart:1144
#2 SchedulerBinding.handleDrawFrame
package:flutter/β¦/scheduler/binding.dart:1090
#3 SchedulerBinding._handleDrawFrame
package:flutter/β¦/scheduler/binding.dart:998
#7 _invoke (dart:ui/hooks.dart:161:10)
...
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@AscentionOne I see, I guess that makes it easier for me to take the decision of weather to build-in the HeroScope inside of AutoRouterWidget
p.s you could also pass the HeroController as a Navigator Observer to AutoRouter() instead of scoping it.
This fixes the issue nicely.
@Milad-Akarie I'm placing a HeroController
inside the navigatorObservers
of AutoRouter.declarative
but it's not working.
Hello! I tried the ways suggested above and the problem persists, is there anything else I can do?
AutoRouteNavigator
is already wrapped with HeroControllerScope
now but its not working. Im on v2.2.0
auto_route: ^2.3.2
class HeroEmptyRouterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return HeroControllerScope(
controller: HeroController(),
child: AutoRouter(),
);
}
}
Does not seem to work. The Hero is not animated.
Also the compiler dose not like this:
Widget build(BuildContext context) {
return AutoRouter(navigatorObservers: [HeroController()]);
}
The argument type 'List<HeroController>' can't be assigned to the parameter type 'List<NavigatorObserver> Function()'.
What is the current solution to this?
auto_route: ^ 2.3.2
class HeroEmptyRouterPage extends StatelessWidget { @override Widget build(BuildContext context) { return HeroControllerScope( controller: HeroController(), child: AutoRouter(), ); } }
ΠΠΎΡ ΠΎΠΆΠ΅, Π½Π΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ. ΠΠ΅ΡΠΎΠΉ Π½Π΅ Π°Π½ΠΈΠΌΠΈΡΠΎΠ²Π°Π½.
Π’Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ·Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΠ° Π½Π΅ ΡΠ°ΠΊΠ°Ρ:
Widget build(BuildContext context) { return AutoRouter(navigatorObservers: [HeroController()]); }
The argument type 'List<HeroController>' can't be assigned to the parameter type 'List<NavigatorObserver> Function()'.
ΠΠ°ΠΊΠΎΠ²ΠΎ ΡΠ΅ΠΊΡΡΠ΅Π΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ?
Hello! you figured out this problem?
Wrapping with HeroControllerScope
didn't work. But adding HeroController
to navigator observers worked for me:
AutoTabsScaffold(
navigatorObservers:() => [HeroController()]
...
)
I am adding HeroController()
, but still the animation doesn't work.
Material app
routerDelegate: getIt<AppRouter>().delegate(
placeholder: (_) => const SplashPage(),
navigatorObservers: () => [HeroController()],
),
class RootWrapperPage extends StatelessWidget {
const RootWrapperPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: getIt<AuthBloc>(),
child: BlocBuilder<AuthBloc, AuthState>(
buildWhen: (previous, current) =>
previous.runtimeType != current.runtimeType,
builder: (_, state) => AutoRouter.declarative(
routes: (_) => [
const SplashRoute(),
if (state is Unauthenticated) const AuthWrapperRoute(),
if (state is Authenticated) const HomeRoute(),
],
),
),
);
}
}
class AuthWrapperPage extends StatelessWidget {
const AuthWrapperPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const AutoRouter();
}
}
@MaterialAutoRouter(
replaceInRouteName: 'Page,Route',
routes: <AutoRoute>[
AutoRoute(
initial: true,
path: '',
page: RootWrapperPage,
children: [
CustomRoute(page: SplashPage),
CustomRoute(
page: AuthWrapperPage,
durationInMilliseconds: splashTransitionMilliseconds,
children: [
CustomRoute(
page: MainAuthPage,
initial: true,
),
CustomRoute(
page: LoginPage,
durationInMilliseconds: splashTransitionMilliseconds,
),
],
),
AutoRoute(page: HomePage),
],
),
],
)
class AppRouter extends _$AppRouter {}
Edit
I ended up duplicating SplashPage
in AuthWrapperPage
and showing it for 1 frame and then navigating to MainAuthPage
.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions
ppe
has you solve this problem? mine also cannot add HeroController to List
edit: should use this syntax :
AutoRouter(
navigatorObservers: ()=> [HeroController()],
),
instead of
AutoRouter(
navigatorObservers: [HeroController()],
),
Hi, I am using
Hero
widget in my application. However, the hero animation is not showing. The Hero widget is set to the product image in theShopPage
and by clicking the image it will navigate to theProductDetailPage
with relativeid
. There should be a hero animation between page transitions. However, it is showing the slide in transition.Another question is since this is a mobile app. Is setting up the
path
mandatory? I know in web applications we have to set up the path. Not sure if I have to in the mobile application, since we can not type the route manually. Thanks!Below is my route setup example.