Flutter通用导航插件universal_navigation的使用
简介
universal_navigation
是一个用于 Flutter 应用程序的核心导航库。它允许使用底部导航栏,并在不同块(Bloc)和页面之间传递数据。
平台兼容性
该插件已在以下平台进行了测试:
- Android;
- iOS;
- Windows 10 64 位;
- Linux(Ubuntu 20.04.1 LTS);
- Web(Chrome)。
注意:MacOS 的支持未被保证,但可以尝试构建。
使用方法
要使用此插件,请在 pubspec.yaml
文件中添加 universal_navigation
作为依赖项。
dependencies:
universal_navigation:
injectable:
dev_dependencies:
injectable_generator:
build_runner:
开始使用
安装步骤
1. 创建全局页面模块
首先,创建一个文件来表示全局页面(或屏幕、Bloc)。
// 文件名: global_flows_module.dart
@module
abstract class GlobalFlowsModule {
@singleton
GlobalFlows get getGlobalFlows => GlobalFlows({
StartPage.routeName: (ctx) => getIt<StartPage>(),
LoginPage.routeName: (ctx) => getIt<LoginPage>(),
BottomNavigationPage.routeName: (ctx) => getIt<BottomNavigationPage>(),
NestedTabPage.routeName: (ctx) => getIt<NestedTabPage>(),
});
}
说明:
GlobalFlows
类已定义在库中。- 使用了
@module
和@singleton
注解,这些来自injectable
包。
2. 创建标签页模块
接下来,创建一个文件来表示标签页流页面(或屏幕、Bloc)。
// 文件名: tab_flows_module.dart
@module
abstract class TabFlowsModule {
@singleton
List<TabFlow> get getTabFlows => [
TabFlow(
page: getIt<FirstTabPage>(),
navigatorKey: GlobalKey<NavigatorState>(),
iconData: Icons.mail,
title: '1'),
TabFlow(
page: getIt<SecondTabPage>(),
navigatorKey: GlobalKey<NavigatorState>(),
iconData: Icons.announcement,
title: '2'),
TabFlow(
page: getIt<ThirdTabPage>(),
navigatorKey: GlobalKey<NavigatorState>(),
iconData: Icons.person,
title: '3'),
];
}
说明:
TabFlow
已定义在库中,包含以下属性:page
: 页面或 Bloc。navigatorKey
: 用于嵌套导航的键。iconData
: 底部导航栏的图标。title
: 底部导航栏的文字。
3. 创建底部导航桥接类
创建一个类实现 BottomNavigationBuilder
和 TabChanger
接口。
// 文件名: default_bottom_nav_bridge.dart
class DefaultBottomNavBridge implements BottomNavigationBuilder, TabChanger {
final BottomNavKey bottomNavKey;
final List<TabFlow> tabFlows;
final Color backgroundColor;
final Color selectedItemColor;
final Color unselectedItemColor;
BottomNavigationBar _bottomNavigationBar;
DefaultBottomNavBridge({
@required this.bottomNavKey,
@required this.tabFlows,
@required this.backgroundColor,
@required this.selectedItemColor,
@required this.unselectedItemColor,
});
@override
Widget build(int currentIndexTab, Function(int) onTabChanged) {
_bottomNavigationBar = BottomNavigationBar(
key: bottomNavKey.key,
backgroundColor: backgroundColor,
selectedItemColor: selectedItemColor,
unselectedItemColor: unselectedItemColor,
currentIndex: currentIndexTab,
items: tabFlows
.map(
(e) => BottomNavigationBarItem(
icon: Icon(e.iconData),
label: e.title,
),
)
.toList(),
onTap: onTabChanged,
);
return _bottomNavigationBar;
}
@override
List<TabFlow> getTabFlows() {
return tabFlows;
}
@override
void onTap(int index) {
_bottomNavigationBar.onTap(index);
}
}
4. 注册默认底部导航桥接类
创建一个文件来注册 DefaultBottomNavBridge
类作为依赖项。
// 文件名: bottom_nav_bridge_module.dart
@module
abstract class BottomNavBridgeModule {
@lazySingleton
DefaultBottomNavBridge get getDefaultBottomNavBridge =>
DefaultBottomNavBridge(
bottomNavKey: getIt<BottomNavKey>(),
tabFlows: getIt<List<TabFlow>>(),
backgroundColor: Colors.white,
selectedItemColor: Colors.redAccent,
unselectedItemColor: Colors.grey,
);
BottomNavigationBuilder get getBottomNavigationBuilder =>
getIt<DefaultBottomNavBridge>();
TabChanger get getTabChanger => getIt<DefaultBottomNavBridge>();
}
5. 合并依赖项
由于 injectable
无法生成库中的依赖项,因此我们使用 get_it
来初始化依赖项。
// 文件名: injection.dart
@injectableInit
void configureInjection(String env) {
initUNavInjection(env);
$initGetIt(environment: env);
initUNavAppNavigatorInjection(env);
_initBottomNavigationInjection(env);
}
void _initBottomNavigationInjection(String env) {
getIt.registerSingleton<BottomNavigationPage>(
BottomNavigationPage(getIt<TabChangeListener>(), getIt<BottomNavigationBuilder>()));
}
6. 修改 main.dart
在 main.dart
中配置依赖注入。
// 文件名: main.dart
void main() {
configureInjection(Environment.prod);
runApp(Application());
}
class Application extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Universal Navigation Test App',
initialRoute: StartPage.routeName,
navigatorKey: getIt<GlobalNavKey>().key,
debugShowCheckedModeBanner: false,
routes: getIt<GlobalFlows>().flows,
);
}
}
7. 运行代码生成
运行代码生成命令:
flutter packages pub run build_runner watch
如果只想运行一次,可以使用:
flutter packages pub run build_runner build
导航与页面间数据传递
默认情况下,您可以使用 NavigationController
进行导航。
// 文件名: start_page.dart
@injectable
class StartPage extends StatefulWidget {
static const routeName = '/start_page';
final NavigationController<EventData> _navigationController;
const StartPage(this._navigationController);
@override
_StartPageState createState() => _StartPageState();
}
class _StartPageState extends State<StartPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Start Page'),
Padding(
padding: const EdgeInsets.only(top: 16),
child: TextButton(
onPressed: () {
widget._navigationController.pushGlobalPage(LoginPage.routeName, eventData: EventData(event: Event.Login, data: 'Data From Start Page'));
},
child: Text('NEXT'),
),
),
],
),
),
),
);
}
}
如果您想自定义传递的数据类型,可以使用 freezed
。
// 文件名: event_union.freezed.dart
part 'event_union.freezed.dart';
[@freezed](/user/freezed)
abstract class EventUnion with _$EventUnion {
const factory EventUnion() = Empty;
const factory EventUnion.login({String data}) = Login;
}
更多关于Flutter通用导航插件universal_navigation的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter通用导航插件universal_navigation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
universal_navigation
是一个用于 Flutter 的通用导航插件,它提供了一种简单且灵活的方式来处理应用程序中的导航逻辑。这个插件可以帮助你在不同的平台(如 Android、iOS、Web 等)上实现一致的导航体验。
安装
首先,你需要在 pubspec.yaml
文件中添加 universal_navigation
插件的依赖:
dependencies:
flutter:
sdk: flutter
universal_navigation: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
基本用法
1. 初始化导航
在你的 main.dart
文件中,初始化 UniversalNavigation
:
import 'package:flutter/material.dart';
import 'package:universal_navigation/universal_navigation.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Universal Navigation Demo',
navigatorKey: UniversalNavigation.navigatorKey,
onGenerateRoute: UniversalNavigation.onGenerateRoute,
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailsScreen(),
},
);
}
}
2. 导航到新页面
你可以使用 UniversalNavigation
提供的 push
方法来导航到新页面:
import 'package:flutter/material.dart';
import 'package:universal_navigation/universal_navigation.dart';
class HomeScreen extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
UniversalNavigation.push(context, '/details');
},
child: Text('Go to Details'),
),
),
);
}
}
3. 返回上一页
你可以使用 pop
方法返回到上一页:
import 'package:flutter/material.dart';
import 'package:universal_navigation/universal_navigation.dart';
class DetailsScreen extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Details'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
UniversalNavigation.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
高级用法
1. 传递参数
你可以在导航时传递参数:
UniversalNavigation.push(context, '/details', arguments: {'id': 123});
在目标页面中,你可以通过 ModalRoute.of(context)
获取传递的参数:
class DetailsScreen extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
final Map<String, dynamic> args = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text('Details'),
),
body: Center(
child: Text('ID: ${args['id']}'),
),
);
}
}
2. 自定义路由
你可以通过 onGenerateRoute
来自定义路由逻辑:
Route<dynamic> _onGenerateRoute(RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => HomeScreen());
case '/details':
return MaterialPageRoute(builder: (_) => DetailsScreen());
default:
return MaterialPageRoute(builder: (_) => NotFoundScreen());
}
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Universal Navigation Demo',
navigatorKey: UniversalNavigation.navigatorKey,
onGenerateRoute: _onGenerateRoute,
initialRoute: '/',
);
}
}