vrouter
vrouter copied to clipboard
Stacked routing from several layers of navigation
Hi, @lulupointu! First of all, I would like to thank you for this beautiful library! Thank you so much for your hard work!
And now to business:
I (and it seems by some issues - not only I) have some difficulty with how to organize routing to achieve such a goal:
Here is the structure of my routing logic:
.
├── /
│ ├── /home
│ │ └── /home/details
│ ├── /settings
│ └── /profile
├── /auth
├── /images/:imagePath
└── * # not found
The real values of the routes are given in the comments. That is, if the comment specifies /home/details
- then the variable RoutesList.homeDetails.path
contains the string '/home/details'
and not 'home/details'
:
import 'package:flutter/material.dart';
import 'package:navigator_comparison/vrouter_app/domain/auth_view/auth_view.dart';
import 'package:navigator_comparison/vrouter_app/domain/home_details_view/home_details_view.dart';
import 'package:navigator_comparison/vrouter_app/domain/home_view/home_view.dart';
import 'package:navigator_comparison/vrouter_app/domain/image_view/image_view.dart';
import 'package:navigator_comparison/vrouter_app/domain/not_found_view/not_found_view.dart';
import 'package:navigator_comparison/vrouter_app/domain/profile_view/profile_view.dart';
import 'package:navigator_comparison/vrouter_app/domain/root_view/root_view.dart';
import 'package:navigator_comparison/vrouter_app/domain/settings_view/settings_view.dart';
import 'package:navigator_comparison/vrouter_app/service/routing/routes_list.dart';
import 'package:vrouter/vrouter.dart';
List<VRouteElement> routesMapping() {
return [
/// "/" -> "/home"
VRouteRedirector(path: RoutesList.root.path, redirectTo: RoutesList.home.path),
/// "/"
VNester(
path: RoutesList.root.path,
name: RoutesList.root.name,
widgetBuilder: (Widget child) => RootView(child: child),
nestedRoutes: [
/// "/home"
VWidget(
path: RoutesList.home.path,
name: RoutesList.home.name,
widget: const HomeView(),
stackedRoutes: [
VWidget(
path: RoutesList.homeDetails.path,
name: RoutesList.homeDetails.name,
widget: const HomeDetailsView(),
),
],
),
/// "/settings"
VWidget(
path: RoutesList.settings.path,
name: RoutesList.settings.name,
widget: const SettingsView(),
),
/// "/profile"
VWidget(
path: RoutesList.profile.path,
name: RoutesList.profile.name,
widget: const ProfileView(),
),
],
),
/// "/auth"
VWidget.builder(
path: RoutesList.auth.path,
name: RoutesList.auth.name,
builder: (BuildContext context, VRouterData data) => AuthView(nextRoute: data.queryParameters[ParamsList.nextRoute.name] ?? ''),
),
/// "/image/:imagePath"
VWidget.builder(
path: RoutesList.imageDetails.path,
name: RoutesList.imageDetails.name,
builder: (BuildContext context, VRouterData data) => ImageView(imagePath: data.pathParameters[ParamsList.imagePath.name] ?? ''),
),
/// "*"
VWidget(
path: '*',
widget: const NotFoundView(),
),
];
}
Basically, the problem is with the ImageView
, which doesn't automatically have a BackButton
. Oh yes, you can't see it in the video, because I added it specifically to the ImageView beforehand 😀:
import 'package:flutter/material.dart';
import 'package:navigator_comparison/common/common_route_viewer.dart';
import 'package:vrouter/vrouter.dart';
class ImageView extends StatelessWidget {
const ImageView({
required this.imagePath,
super.key,
});
final String imagePath;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Image view'),
leading: BackButton(onPressed: () => context.vRouter.historyBack()),
),
backgroundColor: Color.lerp(const Color.fromRGBO(67, 170, 139, 1), Colors.white, 0.90),
body: ListView(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Hero(
tag: imagePath,
child: Image.asset(
imagePath,
),
),
),
),
const CommonRouteViewer(),
],
),
);
}
}
The real picture of ImageView after routing on it:


If I remove the leading, the button doesn't appear. The only way to go back from this screen is to use vRouter.historyBack()
. Which in general looks pretty crusty - you have to override the logic for showing the BackButton inside the AppBar and use vRouter.historyBack()
to go back.
Is there any way to make this more "pretty"? I tried playing around with the location of one screen, inside of which my Nested
screen and ImageView would already be on the same level, but it didn't work out well.
Also, the solution with the aliases from the link at the beginning - also did not help.
If it's useful - the source code of the project I mentioned is available here, and what you might be directly interested in is here.
P.S. And lastly, I'm writing an article comparing go_router
and vrouter
, and this annoying aspect of the latter prevents things from being done the way I want them to be.