Last updated:
0 purchases
implicit navigator
A navigator that manages the page stack for you!
Just build your widget tree and Implicit Navigator will handle the rest.
Core Features #
The following features set Implicit Navigator apart from the official Flutter solution(s):
The navigator stack is constructed and appended to implicitly as your app's data models and widget tree change.
"App-style" and "browser-style" navigation are both supported out of the box:
App-Style - back button goes "up" in a developer-defined navigation hierarchy, potentially undoing multiple
state changes
Browser-Style - back button reverts the last state change
Nesting navigators in the widget tree has first class support with the system back button always popping from the
inner most navigator first.
Additionally, ImplicitNavigator.fromValueNotifier and ImplicitNavigator.selectFromListenable provide out-of-the-box ways
to attach a navigator to a ValueNotifier or Listenable, respectively.
Getting Started #
First decide if you want to use app or browser style navigation. Below are samples for each style, but this is just a
starting off point! You can set the navigation style based on the current platform or mix and match styles in different
navigators within the same app.
App-Style Navigation #
The following implements app-style navigation:
class _AppStyleState extends State<AppStyle> {
int? _index;
@override
Widget build(BuildContext context) {
return ImplicitNavigator<int?>(
value: _index,
depth: _index == null ? 0 : 1,
builder: (context, index, animation, secondaryAnimation) {
return TextButton(
onPressed: () => setState(() {
_index = (index ?? -1) + 1;
}),
onLongPress: () => ImplicitNavigator.of<int?>(context).pop(),
child: Text((index ?? 'Tap To Increment').toString()),
);
},
onPop: (poppedValue, valueAfterPop) => _index = valueAfterPop,
);
}
}
copied to clipboard
ImplicitNavigator takes an optional depth parameter which represents where the user currently is in the app's
navigation flow. When the back button is pressed, the app state is returned to the last value of less depth. ie, the
user moves "up" in the navigation flow.
Using the above example code, imagine a user navigates through the pages as follows:
depth_0:_index=null > depth_1:_index=0 > depth_1:_index=1
If the user then presses back, they will go up in the navigation flow to depth 0: depth_0:_index=null, not
depth_1:_index=0.
If Implicit Navigators are nested within each other in the widget tree, you should build each inner navigator with
MaintainHistory set to true and a distinct PageStorageKey. Implicit Navigator will then cache and restore the
history stack using page storage so that, if a user navigates away from it and then navigates back, it'll retain it's
history stack.
Browser-Style Navigation #
The following implements browser-style navigation:
class _BrowserStyleState extends State<BrowserStyle> {
int? _index;
@override
Widget build(BuildContext context) {
return ImplicitNavigator<int?>(
value: _index,
builder: (context, index, animation, secondaryAnimation) {
return TextButton(
onPressed: () => setState(() {
_index = (_index ?? -1) + 1;
}),
onLongPress: () => ImplicitNavigator.of<int?>(context).pop(),
child: Text((index ?? 'Tap To Increment').toString()),
);
},
onPop: (poppedValue, valueAfterPop) => _index = valueAfterPop,
);
}
}
copied to clipboard
For browser-style navigation, simply leave depth null and do not set MaintainHistory to true on any nested
implicit navigators.
Repeating the example from above, but with browser style navigation:
depth_null:_index=null > depth_null:_index=0 > depth_null:_index=1
If the user then presses back, they will go back to the previous page/app state: depth_null:_index=0.
How It Works #
Implicit Navigator is built on top of the Flutter Navigator 2.0 API. Implicit Navigators operate similar to
ValueListenableBuilder: each one takes in a changing value and a builder. Whenever a new value and/or depth is
supplied, a new page is added to the internal navigator's page stack. When pop is called (by the system or
programmatically), the topmost page is popped and the builder is called with the new topmost value. An onPop callback
should be used to revert any state outside of the navigator.
For convenience, ImplicitNavigator.fromValueNotifier and ImplicitNavigator.selectFromListenable wrap
ValueNotifier and ValueListenable, respectively. They push to the navigator stack when their respective notifier or
listenable changes.
When the system back button is called (or pop is called programmatically), ImplicitNavigator attempts to pop from the
deepest active navigator in the tree, working it's way up to the root navigator until it finds an active navigator that
can handle the pop. A navigator is active if it is in the topmost route of the root navigator and it has not been
manually disabled via ImplicitNavigator.of(context).canPop = false.
ImplicitNavigatorBackButton is also provided as a convenience widget. Use it in your app bar's leading argument to
display a back button that is visible whenever any Implicit Navigator in the widget tree can pop.
Limitations #
Implicit navigator's page history is updated using the flutter build cycle so if a value changes repeatedly between
builds, the page history will not include the intermediate values. This is not fixable for the default constructor
but I am looking into fixing this bug for fromNotifier and selectFromListenable.
Implicit Navigator does not provide any out of the box tools for routing (eg parsing URLs pushed by the browser
or handling deep links). This is intentional. Routing is highly complex and, in my opinion, well outside of the
separation of concerns for a navigator package. To handle routing, use the router of your choice to parse incoming
routes and rebuild the widget tree with the new app state according to the incoming routes. Implicit Navigator will
see any relevant state changes and push the appropriate pages in response.
Contributing #
I highly appreciate any support on this project! If you find an issue or have a feature request feel free to
file a bug or
fork the repo and submit a PR.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.