Flutter学习之导航与路由

Flutter 导航与路由全面指南

一、基础导航概念

1. 导航与路由的区别

  • 导航:指页面之间的跳转行为
  • 路由:页面跳转的路径或规则

2. 核心组件

dart 复制代码
// 基础导航组件
Navigator
MaterialPageRoute
RouteSettings

二、基础导航实现

1. 基本页面跳转

dart 复制代码
// 跳转到新页面
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(),
),
);

// 返回上一页
Navigator.pop(context);

// 带返回值的导航
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: Text('跳转并获取结果'),
onPressed: () async {
// 等待新页面返回结果
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(),
),
);
print('收到返回结果: $result');
},
),
),
);
}
}

class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: Text('返回数据'),
onPressed: () {
// 返回数据给上一个页面
Navigator.pop(context, '这是返回的数据');
},
),
),
);
}
}

2. 多种导航方法

dart 复制代码
// 1. 替换当前页面(不能返回)
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => NewPage(),
),
);

// 2. 跳转到新页面并移除之前所有页面
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => NewPage(),
),
(route) => false, // 返回false表示移除所有之前的页面
);

// 3. 跳转到新页面并保留特定页面
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => NewPage(),
),
ModalRoute.withName('/home'), // 保留名为/home的页面
);

// 4. 弹出到指定页面
Navigator.popUntil(
context,
ModalRoute.withName('/home'),
);

三、命名路由

1. 基本配置

dart 复制代码
void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '命名路由示例',

// 方式1:使用 routes 定义路由表
routes: {
'/': (context) => HomePage(),
'/detail': (context) => DetailPage(),
'/settings': (context) => SettingsPage(),
'/profile': (context) => ProfilePage(),
},

// 方式2:使用 initialRoute 和 routes
initialRoute: '/',

// 方式3:处理未知路由
onUnknownRoute: (settings) {
return MaterialPageRoute(
builder: (context) => NotFoundPage(),
);
},
);
}
}

2. 使用命名路由

dart 复制代码
// 跳转到命名路由
Navigator.pushNamed(context, '/detail');

// 替换命名路由
Navigator.pushReplacementNamed(context, '/detail');

// 跳转到命名路由并移除之前所有
Navigator.pushNamedAndRemoveUntil(
context,
'/detail',
(route) => false,
);

// 带参数的命名路由跳转
Navigator.pushNamed(
context,
'/detail',
arguments: {
'id': 123,
'title': '详情页',
},
);

3. 获取路由参数

dart 复制代码
class DetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 获取路由参数
final args = ModalRoute.of(context)!.settings.arguments as Map?;
final id = args?['id'] ?? 0;
final title = args?['title'] ?? '详情';

return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(child: Text('ID: $id')),
);
}
}

四、路由传参方式

1. 构造函数传参(推荐)

dart 复制代码
// 定义接收参数的页面
class DetailPage extends StatelessWidget {
final int id;
final String title;
final User user;

DetailPage({
required this.id,
required this.title,
required this.user,
});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Column(
children: [
Text('ID: $id'),
Text('用户名: ${user.name}'),
Text('邮箱: ${user.email}'),
],
),
);
}
}

// 使用
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(
id: 123,
title: '用户详情',
user: User(name: '张三', email: 'zhangsan@example.com'),
),
),
);

2. 使用 onGenerateRoute(灵活传参)

dart 复制代码
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
onGenerateRoute: (settings) {
// 处理所有路由
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => HomePage());

case '/detail':
final args = settings.arguments as Map;
return MaterialPageRoute(
builder: (_) => DetailPage(
id: args['id'],
title: args['title'],
user: args['user'],
),
);

case '/product':
final args = settings.arguments as Map;
return MaterialPageRoute(
builder: (_) => ProductPage(
productId: args['productId'],
category: args['category'],
),
);

default:
return MaterialPageRoute(
builder: (_) => NotFoundPage(),
);
}
},
);
}
}

3. 使用路由参数传递复杂对象

dart 复制代码
// 定义数据模型
class Product {
final String id;
final String name;
final double price;

Product({required this.id, required this.name, required this.price});
}

// 跳转时传递对象
Navigator.pushNamed(
context,
'/product',
arguments: {
'product': Product(
id: 'p001',
name: 'Flutter开发指南',
price: 99.9,
),
},
);

// 在目标页面接收
class ProductPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as Map;
final product = args['product'] as Product;

return Scaffold(
appBar: AppBar(title: Text(product.name)),
body: Column(
children: [
Text('商品ID: ${product.id}'),
Text('价格: ¥${product.price}'),
],
),
);
}
}

五、路由守卫

1. 认证检查

dart 复制代码
class MyApp extends StatelessWidget {
final AuthService authService = AuthService();

@override
Widget build(BuildContext context) {
return MaterialApp(
onGenerateRoute: (settings) {
// 路由守卫:检查是否需要登录
if (_needAuth(settings.name!) && !authService.isLoggedIn) {
// 未登录,跳转到登录页
return MaterialPageRoute(
builder: (_) => LoginPage(
onLoginSuccess: () {
// 登录成功后跳转到目标页面
Navigator.pushNamedAndRemoveUntil(
context,
settings.name!,
(route) => false,
);
},
),
);
}

// 正常路由处理
return _buildRoute(settings);
},
);
}

bool _needAuth(String routeName) {
// 需要认证的路由列表
final authRoutes = ['/profile', '/settings', '/order'];
return authRoutes.contains(routeName);
}

Route _buildRoute(RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => HomePage());
case '/login':
return MaterialPageRoute(builder: (_) => LoginPage());
// ... 其他路由
default:
return MaterialPageRoute(builder: (_) => NotFoundPage());
}
}
}

2. 导航观察者

dart 复制代码
class AppNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route route, Route? previousRoute) {
print('推入新路由: ${route.settings.name}');
print('前一路由: ${previousRoute?.settings.name}');

// 可以在这里进行页面统计
Analytics.trackPageView(route.settings.name ?? 'unknown');
}

@override
void didPop(Route route, Route? previousRoute) {
print('返回路由: ${route.settings.name}');
}

@override
void didReplace({Route? newRoute, Route? oldRoute}) {
print('替换路由: ${oldRoute?.settings.name} -> ${newRoute?.settings.name}');
}
}

// 使用
MaterialApp(
navigatorObservers: [AppNavigatorObserver()],
);

六、嵌套导航

1. 底部导航栏 + 嵌套导航器

dart 复制代码
class MainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
int _currentIndex = 0;

// 为每个标签页创建独立的导航器
final List<GlobalKey<NavigatorState>> _navigatorKeys = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
];

// 每个标签页的页面栈
final List<Widget> _pages = [
HomePage(),
SearchPage(),
ProfilePage(),
];

@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
// 处理系统返回键
final currentNavigator = _navigatorKeys[_currentIndex];
if (currentNavigator.currentState!.canPop()) {
// 当前标签页有页面可返回
currentNavigator.currentState!.pop();
return false;
}
// 当前标签页没有页面可返回,退出应用
return true;
},
child: Scaffold(
body: IndexedStack(
index: _currentIndex,
children: _pages.asMap().entries.map((entry) {
final index = entry.key;
final page = entry.value;

return Navigator(
key: _navigatorKeys[index],
onGenerateRoute: (settings) {
return MaterialPageRoute(
builder: (context) => page,
);
},
);
}).toList(),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: '首页',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: '搜索',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: '我的',
),
],
onTap: (index) {
if (_currentIndex == index) {
// 点击当前选中的标签,返回首页
_navigatorKeys[index].currentState?.popUntil(
(route) => route.isFirst,
);
} else {
setState(() {
_currentIndex = index;
});
}
},
),
),
);
}
}

2. Drawer 侧边栏导航

dart 复制代码
class DrawerExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('侧边栏导航')),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
DrawerHeader(
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
radius: 30,
backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
),
SizedBox(height: 10),
Text(
'张三',
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
Text(
'zhangsan@example.com',
style: TextStyle(
color: Colors.white70,
),
),
],
),
),
ListTile(
leading: Icon(Icons.home),
title: Text('首页'),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/');
},
),
ListTile(
leading: Icon(Icons.settings),
title: Text('设置'),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/settings');
},
),
ListTile(
leading: Icon(Icons.help),
title: Text('帮助'),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/help');
},
),
Divider(),
ListTile(
leading: Icon(Icons.exit_to_app),
title: Text('退出登录'),
onTap: () {
Navigator.pop(context);
_showLogoutDialog(context);
},
),
],
),
),
body: Center(child: Text('主内容区域')),
);
}

void _showLogoutDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('确认退出?'),
content: Text('确定要退出当前账号吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('取消'),
),
TextButton(
onPressed: () {
// 执行退出逻辑
Navigator.pop(context);
Navigator.pushNamedAndRemoveUntil(
context,
'/login',
(route) => false,
);
},
child: Text('确定'),
),
],
),
);
}
}

七、自定义路由动画

1. 基础自定义动画

dart 复制代码
// 渐变过渡
class FadeRoute extends PageRouteBuilder {
final Widget page;

FadeRoute({required this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) => page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) => FadeTransition(
opacity: animation,
child: child,
),
transitionDuration: Duration(milliseconds: 300),
);
}

// 使用
Navigator.push(
context,
FadeRoute(page: DetailPage()),
);

2. 滑动过渡

dart 复制代码
// 从右侧滑入
class SlideRightRoute extends PageRouteBuilder {
final Widget page;

SlideRightRoute({required this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) => page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: child,
);
},
transitionDuration: Duration(milliseconds: 300),
);
}

// 从底部滑入
class SlideUpRoute extends PageRouteBuilder {
final Widget page;

SlideUpRoute({required this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) => page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 1),
end: Offset.zero,
).animate(animation),
child: child,
);
},
transitionDuration: Duration(milliseconds: 300),
);
}

3. 缩放过渡

dart 复制代码
class ScaleRoute extends PageRouteBuilder {
final Widget page;

ScaleRoute({required this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) => page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return ScaleTransition(
scale: Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
),
),
child: child,
);
},
transitionDuration: Duration(milliseconds: 300),
);
}

4. 旋转过渡

dart 复制代码
class RotationRoute extends PageRouteBuilder {
final Widget page;

RotationRoute({required this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) => page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return RotationTransition(
turns: Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.linear,
),
),
child: child,
);
},
transitionDuration: Duration(milliseconds: 500),
);
}

5. 组合动画

dart 复制代码
class CombinedRoute extends PageRouteBuilder {
final Widget page;

CombinedRoute({required this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) => page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: Tween<double>(
begin: 0.5,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
),
child: child,
),
),
);
},
transitionDuration: Duration(milliseconds: 400),
);
}

八、Hero 动画

1. 基础 Hero 动画

dart 复制代码
// 第一个页面
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(),
),
);
},
child: Hero(
tag: 'imageHero',
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: NetworkImage('https://example.com/image.jpg'),
fit: BoxFit.cover,
),
),
),
),
),
),
);
}
}

// 第二个页面
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('详情')),
body: Center(
child: Hero(
tag: 'imageHero',
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: NetworkImage('https://example.com/image.jpg'),
fit: BoxFit.cover,
),
),
),
),
),
);
}
}

2. 多个 Hero 动画

dart 复制代码
// 列表项
class ProductItem extends StatelessWidget {
final Product product;

ProductItem({required this.product});

@override
Widget build(BuildContext context) {
return ListTile(
leading: Hero(
tag: 'image_${product.id}',
child: CircleAvatar(
backgroundImage: NetworkImage(product.imageUrl),
),
),
title: Hero(
tag: 'title_${product.id}',
child: Material(
color: Colors.transparent,
child: Text(
product.name,
style: TextStyle(fontSize: 16),
),
),
),
subtitle: Text('¥${product.price}'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailPage(product: product),
),
);
},
);
}
}

// 详情页
class ProductDetailPage extends StatelessWidget {
final Product product;

ProductDetailPage({required this.product});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('商品详情')),
body: Column(
children: [
Hero(
tag: 'image_${product.id}',
child: Image.network(
product.imageUrl,
width: double.infinity,
height: 300,
fit: BoxFit.cover,
),
),
Padding(
padding: EdgeInsets.all(16),
child: Hero(
tag: 'title_${product.id}',
child: Material(
color: Colors.transparent,
child: Text(
product.name,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
),
),
],
),
);
}
}

九、路由管理最佳实践

1. 路由集中管理

dart 复制代码
// routes.dart
class AppRoutes {
// 路由名称常量
static const String home = '/';
static const String login = '/login';
static const String register = '/register';
static const String profile = '/profile';
static const String settings = '/settings';
static const String detail = '/detail';
static const String notFound = '/404';

// 路由生成器
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case home:
return MaterialPageRoute(builder: (_) => HomePage());

case login:
return MaterialPageRoute(builder: (_) => LoginPage());

case register:
return MaterialPageRoute(builder: (_) => RegisterPage());

case profile:
final args = settings.arguments as Map?;
return MaterialPageRoute(
builder: (_) => ProfilePage(
userId: args?['userId'] ?? '',
),
);

case detail:
final args = settings.arguments as Map;
return MaterialPageRoute(
builder: (_) => DetailPage(
id: args['id'],
title: args['title'],
),
);

default:
return MaterialPageRoute(builder: (_) => NotFoundPage());
}
}
}

// main.dart
void main() {
runApp(
MaterialApp(
title: '我的应用',
theme: ThemeData(primarySwatch: Colors.blue),
initialRoute: AppRoutes.home,
onGenerateRoute: AppRoutes.generateRoute,
onUnknownRoute: (settings) {
return MaterialPageRoute(
builder: (_) => NotFoundPage(),
);
},
),
);
}

2. 导航服务

dart 复制代码
class NavigationService {
static GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

// 跳转到命名路由
static Future<dynamic> navigateTo(String routeName, {dynamic arguments}) {
return navigatorKey.currentState!.pushNamed(
routeName,
arguments: arguments,
);
}

// 替换当前路由
static Future<dynamic> replaceWith(String routeName, {dynamic arguments}) {
return navigatorKey.currentState!.pushReplacementNamed(
routeName,
arguments: arguments,
);
}

// 跳转并清除所有历史
static Future<dynamic> navigateAndRemoveUntil(
String routeName,
bool Function(Route<dynamic>) predicate, {
dynamic arguments,
}) {
return navigatorKey.currentState!.pushNamedAndRemoveUntil(
routeName,
predicate,
arguments: arguments,
);
}

// 返回
static void goBack([dynamic result]) {
return navigatorKey.currentState!.pop(result);
}

// 检查是否可以返回
static bool canGoBack() {
return navigatorKey.currentState!.canPop();
}
}

// 使用
// 在任何地方都可以调用导航
NavigationService.navigateTo('/detail', arguments: {'id': 123});

3. 路由守卫服务

dart 复制代码
class RouteGuard {
final AuthService authService;

RouteGuard({required this.authService});

// 检查路由是否需要认证
bool needAuth(String routeName) {
final protectedRoutes = [
'/profile',
'/settings',
'/order',
'/cart',
];
return protectedRoutes.contains(routeName);
}

// 检查用户权限
bool hasPermission(String routeName) {
final userRole = authService.currentUser?.role;

switch (routeName) {
case '/admin':
return userRole == 'admin';
case '/manager':
return userRole == 'admin' || userRole == 'manager';
default:
return true;
}
}

// 获取重定向路由
String? getRedirectRoute(String routeName) {
if (needAuth(routeName) && !authService.isLoggedIn) {
return '/login';
}

if (!hasPermission(routeName)) {
return '/unauthorized';
}

return null;
}
}

十、第三方路由库

1. Go Router(官方推荐)

yaml 复制代码
dependencies:
go_router: ^6.0.0
dart 复制代码
import 'package:go_router/go_router.dart';

final GoRouter router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomePage(),
routes: [
GoRoute(
path: 'detail/:id',
builder: (context, state) {
final id = state.pathParameters['id'];
return DetailPage(id: id!);
},
),
GoRoute(
path: 'profile',
builder: (context, state) => ProfilePage(),
),
],
),
GoRoute(
path: '/login',
builder: (context, state) => LoginPage(),
),
],

// 路由守卫
redirect: (context, state) {
final isLoggedIn = false; // 从状态管理获取
final isLoggingIn = state.matchedLocation == '/login';

if (!isLoggedIn && !isLoggingIn) {
return '/login';
}

if (isLoggedIn && isLoggingIn) {
return '/';
}

return null;
},

// 错误页面
errorBuilder: (context, state) => NotFoundPage(),
);

// 在 MaterialApp 中使用
MaterialApp.router(
routerConfig: router,
);

// 使用
context.go('/detail/123');// 跳转
context.pop();// 返回

2. Auto Route

yaml 复制代码
dependencies:
auto_route: ^4.0.0

dev_dependencies:
auto_route_generator: ^4.0.0
build_runner: ^2.0.0
dart 复制代码
// 定义路由
@MaterialAutoRouter(
replaceInRouteName: 'Page,Route',
routes: [
AutoRoute(page: HomePage, initial: true),
AutoRoute(page: DetailPage),
AutoRoute(page: ProfilePage),
],
)
class $AppRouter {}

// 生成路由文件
// flutter pub run build_runner build

// 使用
final router = AppRouter();
MaterialApp.router(
routerDelegate: router.delegate(),
routeInformationParser: router.defaultRouteParser(),
);

十一、调试技巧

1. 查看路由栈

dart 复制代码
// 打印当前路由栈
void printRouteStack(BuildContext context) {
Navigator.of(context).widget.pages.forEach((page) {
print('Route: ${page.name}');
});
}

// 或者使用
Navigator.of(context).toStringDeep();

2. 路由调试组件

dart 复制代码
class RouteDebugWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('路由栈信息'),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('当前路由: ${ModalRoute.of(context)?.settings.name}'),
Divider(),
Text('路由栈:'),
...Navigator.of(context).widget.pages.map((page) {
return Text('- ${page.name ?? '未命名'}');
}).toList(),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('关闭'),
),
],
),
);
},
child: Icon(Icons.route),
);
}
}

总结

Flutter 导航与路由系统非常强大,提供了多种方式来管理页面跳转:

  1. 基础导航 :适合简单应用,使用 Navigator.push/pop
  2. 命名路由:适合中小型应用,便于管理
  3. 路由守卫:实现权限控制和认证检查
  4. 嵌套导航:处理复杂的页面结构
  5. 自定义动画:提升用户体验
  6. 第三方库:大型应用推荐使用 Go Router 或 Auto Route

选择适合项目规模的方案,并保持路由逻辑的清晰和可维护性。对于大多数应用,推荐使用命名路由结合路由守卫的方式,既简单又灵活。

相关推荐
咕泡科技2 小时前
从0到1系统学习大模型:一份接地气的入门指南
人工智能·python·学习
无巧不成书02182 小时前
Java数值字面量速查表
java·开发语言·python·开发者·字面量
美式请加冰2 小时前
模拟的介绍和使用
java·开发语言·算法
你怎么知道我是队长2 小时前
计算机系统基础21---计算机的基本组成---Cache的地址映射方式
学习
菜菜小狗的学习笔记2 小时前
剑指Offer算法题(二)栈、队列、堆
java·开发语言
aaajj2 小时前
【Android】appops学习
android·学习
山川行2 小时前
Git学习笔记:Git进阶操作
笔记·git·vscode·学习·编辑器·visual studio code
nqqcat~2 小时前
hlist哈希链表学习笔记
学习·链表·哈希算法
李宥小哥2 小时前
SQLite04-表数据管理
java·jvm·数据库