Flutter隐式导航插件implicit_navigator的使用
Flutter隐式导航插件implicit_navigator的使用
标题
Flutter隐式导航插件implicit_navigator的使用
内容
A navigator that manages the page stack for you! Just build your widget tree and Implicit Navigator will handle the rest.
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’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 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,
);
}
}
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 its 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,
);
}
}
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 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 its 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
andselectFromListenable
. - 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.
示例代码
更多关于Flutter隐式导航插件implicit_navigator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter隐式导航插件implicit_navigator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter应用中使用implicit_navigator
插件来实现隐式导航的一个简单示例。implicit_navigator
允许你通过URL路由来隐式地导航到应用的不同部分,非常适合于深度链接(deep linking)或网页视图导航的场景。
首先,你需要在你的pubspec.yaml
文件中添加implicit_navigator
依赖:
dependencies:
flutter:
sdk: flutter
implicitly_animated_reorderable_list: ^0.4.0 # 确保版本是最新的,这里仅为示例
implicit_navigator: ^x.y.z # 替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,设置你的Flutter应用来使用implicit_navigator
。这里是一个基本的实现步骤:
- 定义路由映射:
在你的main.dart
文件中,定义一个路由映射,将URL路径映射到你的Flutter页面。
import 'package:flutter/material.dart';
import 'package:implicit_navigator/implicit_navigator.dart';
import 'your_page.dart'; // 假设你有一个YourPage小部件
void main() {
runApp(ImplicitlyAnimatedApp(
home: ImplicitNavigator(
routes: {
'/': (context, settings) => YourHomePage(),
'/your_page': (context, settings) => YourPage(),
},
onGenerateRoute: (settings) {
// 你可以在这里处理未定义的路由
return MaterialPageRoute<void>(
builder: (context) => Scaffold(
body: Center(
child: Text('404 Not Found'),
),
),
);
},
),
));
}
- 创建页面:
创建你的Flutter页面,例如your_page.dart
:
import 'package:flutter/material.dart';
class YourPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your Page'),
),
body: Center(
child: Text('Welcome to Your Page!'),
),
);
}
}
- 使用隐式导航:
你可以使用ImplicitlyAnimatedRoute
或Navigator.pushNamed
等方法来进行隐式导航。不过,为了简单起见,这里展示如何通过URL来触发导航(例如,在Web应用中)。
在Web应用中,你可以使用url_launcher
包来模拟点击一个链接:
import 'package:flutter/material.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:url_launcher/url_launcher.dart' as url_launcher;
class YourHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
// 这里模拟点击一个链接来导航到/your_page
if (await url_launcher.canLaunch('your_page')) {
// 注意:在实际Web应用中,这里应该是完整的URL,例如 '/your_page'
// 但为了演示,我们直接使用路由名称。在真实场景中,你可能需要处理URL的解析和映射。
Navigator.pushNamed(context, '/your_page');
} else {
throw 'Could not launch your_page';
}
},
child: Text('Go to Your Page'),
),
),
);
}
}
注意:在上面的代码中,url_launcher
用于模拟点击链接,但实际上在Web应用中,你可以直接通过URL来改变路由。这个示例主要是为了展示如何在Flutter应用中处理这种隐式导航的概念。
- 处理深度链接:
在Web应用中,你可能需要处理从外部链接直接进入特定页面的情况。这通常涉及到在main.dart
的onGenerateInitialRoutes
回调中处理URL参数。
ImplicitNavigator(
// ...
onGenerateInitialRoutes: (navigator, initialRoute) {
// 根据initialRoute来处理深度链接
if (initialRoute == '/your_page') {
return [
ImplicitlyAnimatedRoute<void>(
settings: RouteSettings(name: '/your_page'),
builder: (context) => YourPage(),
),
];
}
return [
ImplicitlyAnimatedRoute<void>(
settings: RouteSettings(name: '/'),
builder: (context) => YourHomePage(),
),
];
},
// ...
)
这个示例展示了如何使用implicit_navigator
插件来实现基本的隐式导航功能。根据你的具体需求,你可能需要调整路由映射和页面处理逻辑。