Flutter导航管理插件nav的使用
Flutter导航管理插件nav的使用
Welcome to Nav 👋
提供了一种简单的方式来实现页面导航,包含许多路由功能。支持Android和iOS平台。
Install
在pubspec.yaml
文件中添加nav
依赖:
dependencies:
nav: ^{latest version}
Usage
-
在您的App State中添加
Nav
mixin:import 'package:nav/nav.dart'; class _MyAppState extends State<MyApp> with Nav
-
覆盖
get navigatorKey
方法,并提供您在MaterialApp.navigatorKey
中使用的key:class MyApp extends StatefulWidget { static GlobalKey<NavigatorState> navigatorKey = GlobalKey(); // This widget is the root of your application. @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> with Nav { @override GlobalKey<NavigatorState> get navigatorKey => MyApp.navigatorKey; @override Widget build(BuildContext context) { return MaterialApp( navigatorKey: navigatorKey, ...
-
使用push方法进行页面跳转:
//dynamic Nav.push(Widget, navAni: NavAni.Blink); //or Nav.pushFromRight(Widget); Nav.pushFromLeft(Widget); Nav.pushFromTop(Widget); Nav.pushFromBottom(Widget); Nav.pushReplacement(Widget); Nav.pushWithRippleEffect(Widget, centerAlignment : Alignment.bottomRight, centerOffset : Offset(10, 10)); Nav.clearAllAndPush(Widget); enum NavAni { Left, Right, Top, Bottom, Fade, Ripple, Blink }
-
所有方法都可以返回值:
//from bottom screen final result = await Nav.pushFromRight(TopScreen) //you can get result from TopWidget //from top screen Nav.pop(context, result: {"key": "value", "key2": 2})
-
可以定义类型与
NavScreen
及pushResult
方法配合使用:TopScreen extends StatelessWidget with NavScreen<String> or TopScreen extends StatefulWidget with NavScreen<String> ///from bottom screen final result = await Nav.pushResult(TopScreen()); ///result type will be String? ///from top screen ///return Type will be fixed by Generic NavScreen<Result> popResult(context, result: 'Data to return'); ///from Widget widget.popResult(context, result: 'Data to return'); ///from State
示例代码
下面是一个完整的示例demo,展示了如何使用nav
插件进行页面导航:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:nav/nav.dart';
import 'package:nav/screen/nav_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
static GlobalKey<NavigatorState> navigatorKey = GlobalKey();
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with Nav {
@override
GlobalKey<NavigatorState> get navigatorKey => MyApp.navigatorKey;
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: navigatorKey,
title: 'Nav Demo',
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
iconTheme: const IconThemeData(color: Colors.blue),
textTheme: const TextTheme(),
bottomSheetTheme: const BottomSheetThemeData(backgroundColor: Colors.transparent),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget with NavScreen<SimpleResult> {
MyHomePage({Key? key, this.navType}) : super(key: key);
final NavType? navType;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool showBackButton = false;
Color? bgColor;
bool get isHome => !showBackButton;
@override
void initState() {
bgColor = getRandomColor();
super.initState();
}
void checkCanPop() async {
if (await Nav.canPop()) {
setState(() {
this.showBackButton = true;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: bgColor,
floatingActionButton: FloatingActionButton(
onPressed: () async {
final result = await MessageDialog('Test String').show();
print(result);
},
tooltip: 'Ripple',
child: Icon(Icons.open_in_new),
),
body: SafeArea(
child: Stack(
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () async => onResult(
context,
await Nav.pushFromTop(
MyHomePage(navType: NavType.Top))),
icon: icon(Icons.vertical_align_bottom),
)
],
),
Expanded(
child: Container(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () async {
onResult(
context,
await Nav.pushFromLeft(MyHomePage(
navType: NavType.Left)));
},
icon: icon(Icons.keyboard_arrow_right),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
child: icon(iconData),
onTap: () {
if (isHome) {
Nav.clearAllAndPush(MyHomePage(
navType: NavType.ClearAll,
));
} else {
widget.popResult(context, SimpleResult.failure());
}
},
),
isHome
? Text("Click an Arrow",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w700))
: Container(),
],
),
IconButton(
onPressed: () async => onResult(
context,
await Nav.pushFromRight(MyHomePage(
navType: NavType.Right))),
icon: icon(Icons.keyboard_arrow_left),
),
],
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () async => onResult(
context,
await Nav.pushFromBottom(
MyHomePage(navType: NavType.Bottom))),
icon: icon(Icons.vertical_align_top),
)
],
),
],
),
!showBackButton
? Container()
: IconButton(
onPressed: () => Nav.pop(context),
icon: icon(Platform.isIOS
? Icons.arrow_back_ios
: Icons.arrow_back),
)
],
),
),
);
}
Icon icon(IconData data) {
return Icon(
data,
size: 30,
color: Colors.white,
);
}
IconData get iconData {
switch (widget.navType) {
case NavType.Top:
return Icons.vertical_align_top;
case NavType.Bottom:
return Icons.vertical_align_bottom;
case NavType.Left:
return Icons.keyboard_arrow_left;
case NavType.Right:
return Icons.keyboard_arrow_right;
case NavType.Ripple:
return Icons.archive;
case NavType.ClearAll:
return Icons.border_clear;
default:
return Icons.home;
}
}
SnackBar createSnackBar(BuildContext context, String message) {
return SnackBar(
elevation: 0,
behavior: SnackBarBehavior.fixed,
backgroundColor: Colors.transparent,
content: GestureDetector(
onTap: () {},
child: Container(
color: Colors.transparent,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Center(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 11),
child: Center(
child: Text(message,
style: TextStyle(
color: Colors.white,
fontSize: 14,
fontStyle: FontStyle.normal,
)),
),
decoration: BoxDecoration(
color: Color(0xff5a8fee),
borderRadius: BorderRadius.circular(5))),
),
],
),
),
));
}
void onResult(BuildContext context, SimpleResult result) {
if (result.isSuccess) {
final snackbar =
createSnackBar(context, "Result is Success: ${result.toString()}");
ScaffoldMessenger.of(context).showSnackBar(snackbar);
}
}
}
这个示例展示了如何使用nav
插件进行页面导航、传递参数以及处理返回结果。希望这对您有所帮助!
更多关于Flutter导航管理插件nav的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter导航管理插件nav的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,flutter_navigator
或者更常见的 flutter/material
提供的导航功能是实现页面跳转和管理的核心。虽然没有一个特定的名为 nav
的官方插件,但通常我们指的是 Flutter 自带的导航功能。以下是如何使用 Flutter 的导航管理功能的代码示例。
1. 设置基本导航
首先,确保你的 Flutter 项目已经设置好,并包含必要的依赖(主要是 flutter/material
)。
dependencies:
flutter:
sdk: flutter
2. 创建主页面和次级页面
主页面 (main.dart)
import 'package:flutter/material.dart';
import 'second_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
},
child: Text('Go to Second Screen'),
),
),
);
}
}
次级页面 (second_screen.dart)
import 'package:flutter/material.dart';
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Screen'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
3. 使用命名路由(可选)
如果你的应用有多个页面,使用命名路由可以使导航管理更加清晰。
修改主页面以使用命名路由
import 'package:flutter/material.dart';
import 'second_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/',
routes: {
'/': (context) => MyHomePage(),
'/second': (context) => SecondScreen(),
},
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/second');
},
child: Text('Go to Second Screen'),
),
),
);
}
}
4. 传递参数
有时候,你可能需要在页面之间传递数据。这可以通过构造函数参数或 Navigator
的参数功能实现。
修改次级页面以接收参数
import 'package:flutter/material.dart';
class SecondScreen extends StatelessWidget {
final String message;
SecondScreen({required this.message});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Screen'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(message),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
],
),
),
);
}
}
修改主页面以传递参数
import 'package:flutter/material.dart';
import 'second_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/',
routes: {
'/': (context) => MyHomePage(),
'/second': (context) => SecondScreen(), // Note: We will instantiate with arguments later
},
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(
context,
'/second',
arguments: {'message': 'Hello from First Screen!'},
).then((result) {
// Handle result if needed
});
},
child: Text('Go to Second Screen with Message'),
),
),
);
}
}
在 SecondScreen
中接收参数:
import 'package:flutter/material.dart';
class SecondScreen extends StatelessWidget {
SecondScreen({Key? key, required this.message}) : super(key: key);
final String message;
@override
Widget build(BuildContext context) {
final routeArgs = ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>;
String msg = routeArgs['message'] ?? 'No message received';
return Scaffold(
appBar: AppBar(
title: Text('Second Screen'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(msg),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
],
),
),
);
}
}
这段代码展示了如何在 Flutter 中使用导航管理功能,包括基本的页面跳转、使用命名路由以及页面间传递参数。希望这些示例对你有帮助!