Last updated:
0 purchases
flyroutes
FlyRoute #
A Stack that shows a single child from a list of children. Similar in concept to IndexedStack, but it uses Strings as keys and has a number of extra features like child nesting, custom animations and path arguments.
đ¨ Installation #
dependencies:
flyRoute: ^1.2.1
copied to clipboard
â Import #
import 'package:flyRoute/flyRoute.dart';
copied to clipboard
đšī¸ Usage #
To configure a flyRoute provide it with a routing table by settings the .routes value. Declare the paths that you want to support and their corresponding views:
String currentPath = "page1";
...
return flyRoute(
path: currentPath,
unknownPathBuilder: (_) => Custom404Page(),
routes: {
["page1"]: (_) => Page1(),
["page2"]: (_) => Page2(),
});
}
copied to clipboard
A route can match multiple path values. For example this will match when the path value is / or /home:
["home", "/"]: (_) => Home(),
copied to clipboard
Relative paths #
flyRoute also allows you to easily declare relative paths by wrapping one flyRoute within another.
For example, you could define a simple nested structure like:
return flyRoute(
path: path,
routes: {
["home"]: (_) => HomePage(),
["news"]: (_) => NewsPage(),
["settings/"]: (_) => PflyRoute
routes: {
["profile", ""]: (_) => ProfilePage(),
["notifications"]: (_) => NotificationsPage(),
},
),
},
);
copied to clipboard
Which results in the following potential routes:
/home
/news
/settings/profile
/settings/notifications
Scaffold Builder / Nesting #
To support the common use case of shared navigation or app chrome there is scaffoldBuilder which lets you wrap any Widget around the current flyRoute child.
This means you can create a basic tab-scaffold like this:
return flyRoute(
path: currentPath,
scaffoldBuilder: (_, child) =>
TabScaffold(
child: child,
onTabPressed: (value){
setState(() => _currentPath = value)
}})),
routes: {
["/home"]: (_) => HomePage(),
["/settings"]: (_) => SettingsPage()
["/explore"]: (_) => ExplorePage(),
},
);
}
copied to clipboard
Exact vs Partial Matches
Each route can be configured to accept exact or partial matches. For convenience, flyRoute makes some assumptions based on the presence of a trailing slash in your paths:
Routes with no trailing slash in the are assumed to be an exact match:
["details"]: (_) => Details(), // matches only `/details`
copied to clipboard
Routes with trailing slash are assumed be a partial match:
["details/"]: (_) => Details(), // matches any of `/details/`, `/details/12`, `/details/id=12&foo=99` etc
copied to clipboard
If multiple route paths are defined, only the first entry in the path list is considered for this default behavior:
["details", "/"]: (_) => Details(), // matches only `/details` or '/' exactly
copied to clipboard
You can disable this default behavior by wrapping your view in a RouteConfig widget (shown below).
Using RouteConfig to set optional params #
To configure additional options on a route, you can wrap it in a RouteConfig widget:
["/admin"]: (_) => RouteConfig(
maintainState: false, // Tell this route not to maintain state
exactMatch: false, // Tell this route it does not need an exact match (it can be matched as a prefix)
onBeforeEnter: (newRoute) => return isLoggedIn == true, // Return false here to prevent the path from changing
child: AdminPage())
copied to clipboard
Arguments #
You can pass arguments to your routes using either path based or query string args.
To use path based args you embed the name of the params in the route itself as: "details/:foo/:bar", then extract them from stack.args with the same names:
flyRoute(
path: "details/10/20",
routes: {
["details/:foo/:bar"]: (stack) => DetailsPage(foo: stack.args["foo"], bar: stack.args["bar"]),
}
)
copied to clipboard
With query string style, the parsing is the same, but the names are embedded in the path rather than the route:
flyRoute(
path: "/details?foo=10&bar=20",
routes: {
["details/"]: (stack) => DetailsPage(foo: stack.args["foo"], bar: stack.args["bar"]),
}
)
copied to clipboard
Full Example #
There are several other features not mentioned here, including custom route transitions, support for unknown paths (404) and a caseInsensitive setting.
For a full API tour, you can view the following code sample:
return flyRoute(
// Path is the source of truth for each stack, usually this is shared by all child stacks
path: currentPath,
// Optional: Provide custom widget for unknown paths
unknownPathBuilder: (_) => Center(child: Text("Custom 404 Page")),
// Optional: Provide custom animationIn (default is no animation)
transitionBuilder: (_, stack, anim1) => FadeTransition(opacity: anim1, child: stack),
// Optional: Provide duration for animationIn
transitionDuration: Duration(milliseconds: 200),
// By default pages are case insensitive, like a web server. But you can turn this off
caseSensitive: true,
// Define all matching routes for this stack
routes: {
["home", "/"]: (_) => HomePage(),
// Example of a route guard, you can return false to block the change
["admin"]: (_) => RouteConfig(
child: AdminPage(),
onBeforeEnter: (_){
if (isLoggedIn) return true;
scheduleMicrotask(() => setState(() => currentPath = "home"));
return false;
},
),
// Adding a "/" at the end of any path indicates it can match as a prefix but you can override this
["settings/"]: (_) => PflyRoute
// Wrap all settings routes in a shared scaffold
scaffoldBuilder: (_, stack) => Column(children: [
Padding(padding: EdgeInsets.all(20), child: Text("Shared Settings App Bar")), // Settings Header
Expanded(child: stack),
]),
// Define child routes for settings section
routes: {
// By adding a "" alias, the first route will match both `/settings/alerts` and `/settings/`
["alerts", ""]: (_) => AlertsPage(),
["profile"]: (_) => ProfilePage(),
["billing/:foo/:bar"]: (stack) => BillingPage(id: "${stack.args["foo"]}_${stack.args["bar"]}"),
},
),
},
);
copied to clipboard
đ Bugs/Requests #
If you encounter any problems please open an issue. If you feel the library is missing a feature, please raise a ticket on Github and we'll look into it. Pull request are welcome.
đ License #
MIT License
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.