Flutter 路由
路由简介
Route
一个路由是一个屏幕或页面的抽象
Navigator
管理路由的组件,Navigator 可以通过路由入栈和出栈来实现页面之间的跳转
常用属性:
initialRoute:初始路由,即默认页面
onGenerateRoute:动态路由(根据规则,匹配动态路由)
onUnknownRoute:未知路由,也就是404
routes:路由集合
匿名路由
Navigator
push():跳转到指定组件
Navigator.push( context, MaterialPageRoute( builder: (context) => 组件名称(), settings: const RouteSettings( name: String, // 路由名称 arguments: { String: dynamic, // 参数 }, ), ) )
pop():回退
Navigator.pop(context)
示例:
import 'package:flutter/material.dart'; import '08_navigator/navigator_01_anonymous.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: "Flutter Demo", // home: Home(), // 声明路由 routes: { 'home': (context) => const Home(), 'product': (context) => const Product(), }, // 初始路由 initialRoute: 'home', debugShowCheckedModeBanner: false, ); } }
import 'package:flutter/material.dart'; // 首页 class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('匿名路由'), ), body: ListView( padding: const EdgeInsets.all(10), children: [ ElevatedButton( onPressed: () { // 匿名路由跳转 --基本用法 Navigator.push( context, MaterialPageRoute(builder: (context) => const Product()), ); }, child: const Text('跳转到商品页面'), ), ElevatedButton( onPressed: () { // 匿名路由跳转 -- 传参方法 1 Navigator.push( context, MaterialPageRoute( builder: (context) => const Product(), settings: const RouteSettings( name: '带参数的商品页面', // 修改路由名称 arguments: { 'userName': 'zhangsan', 'age': 23, }, ), ), ); }, child: const Text('跳转带传参 settings'), ), ElevatedButton( onPressed: () { // 匿名路由跳转-- 传参方法 2 Navigator.push( context, MaterialPageRoute( builder: (context) => const ProductDetail(id: '123'), ), ); }, child: const Text('跳转带传参 属性'), ), ], ), ); } } // 商品页 class Product extends StatelessWidget { const Product({Key? key}) : super(key: key); @override Widget build(BuildContext context) { dynamic settings = ModalRoute.of(context)?.settings; print('settings: $settings'); return Scaffold( appBar: AppBar( // 传参方法 1:通过 settings 接收参数 title: Text(settings?.name == null ? '商品页面' : settings.name), ), body: ListView( padding: const EdgeInsets.all(10), children: [ Text( // 传参方法 1:通过 settings 接收参数 '主页传递的参数是: ${settings.arguments}', style: const TextStyle( fontSize: 26, color: Colors.red, ), ), ElevatedButton( onPressed: () { // 回退 return Navigator.pop(context); }, child: const Text('返回'), ), ], ), ); } } // 商品详情 class ProductDetail extends StatelessWidget { final String id; const ProductDetail({ Key? key, required this.id, }) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('商品详情'), ), body: ListView( padding: const EdgeInsets.all(10), children: [ // 传参方法 2:通过 类属性 接收参数 Text( '主页传递的参数是: $id', style: const TextStyle( fontSize: 26, color: Colors.red, ), ), ElevatedButton( onPressed: () { // 回退 return Navigator.pop(context); }, child: const Text('返回'), ), ], ), ); } }
命名路由
(1)、声明路由
routes:路由表(Map类型)
initialRoute:初始路由
onUnknownRoute:未知路由 - 404
(2)、跳转到命名路由
Navigator.pushNamed(context, '路由名称');
示例:
import 'package:flutter/material.dart'; import '08_navigator/navigator_02_namedRoute.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: "Flutter Demo", // home: Home(), // 声明路由 routes: { 'home': (context) => const Home(), 'product': (context) => const Product(), }, // 初始路由 initialRoute: 'home', // 未知路由 onUnknownRoute: (RouteSettings setting) => MaterialPageRoute( builder: (context) => const UnknownPage(), ), // 动态路由 debugShowCheckedModeBanner: false, ); } }
import 'package:flutter/material.dart'; // 首页 class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('命名路由'), ), body: ListView( padding: const EdgeInsets.all(10), children: [ ElevatedButton( // 命名路由跳转 onPressed: () => Navigator.pushNamed(context, 'product'), child: const Text('跳转到商品页面'), ), // 命名路由传参 ElevatedButton( // 命名路由跳转 onPressed: () => Navigator.pushNamed( // 上下文 context, // 路由名称 'product', // 参数 arguments: <String, dynamic>{ "title": "我是首页传过来的参数", "age": 28, "viewFlag": true, }, ), child: const Text('跳转到商品页面带入参'), ), // 未知路由跳转 ElevatedButton( // 命名路由跳转 onPressed: () => Navigator.pushNamed(context, 'user'), child: const Text('跳转到不存在的路由'), ), ], ), ); } } // 商品 class Product extends StatelessWidget { const Product({Key? key}) : super(key: key); @override Widget build(BuildContext context) { // 接收传参,可能是 null final arguments = ModalRoute.of(context)!.settings.arguments; return Scaffold( appBar: AppBar( title: const Text('商品页面'), ), body: ListView( padding: const EdgeInsets.all(10), children: [ // 参数 Text( '接收的参数是:$arguments', style: const TextStyle( fontSize: 26, color: Colors.red, ), ), ElevatedButton( onPressed: () { // 返回 return Navigator.pop(context); }, child: const Text('返回'), ) ], ), ); } } // 404 class UnknownPage extends StatelessWidget { const UnknownPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('404'), ), body: Container( padding: const EdgeInsets.all(10), child: const Text('页面飞到太空去了……'), ), ); } }
动态路由
动态路由是指通过 onGeneratedRoute 属性指定的路由
示例:
import 'package:flutter/material.dart'; import '08_navigator/navigator_03_onGeneratedRoute.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: "Flutter Demo", // home: Home(), // 动态路由 onGenerateRoute: (RouteSettings setting) { print('setting: $setting'); print('当前路径:${setting.name}'); // 匹配首页 / if (setting.name == '/') { return MaterialPageRoute(builder: (context) => const Home()); } // 匹配商品页 /product if (setting.name == '/product') { return MaterialPageRoute(builder: (context) => const Product()); } // 匹配商品详情页 /product/:id Uri uri = Uri.parse(setting.name ?? ''); print('uri: $uri'); if (uri.pathSegments.length == 2 && uri.pathSegments.first == 'product') { String id = uri.pathSegments[1]; return MaterialPageRoute(builder: (context) => ProductDetail(id: id)); } return MaterialPageRoute(builder: (context) => const UnknownPage()); }, debugShowCheckedModeBanner: false, ); } }
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('命名路由'), ), body: ListView( padding: const EdgeInsets.all(10), children: [ ElevatedButton( // 命名路由跳转 onPressed: () => Navigator.pushNamed(context, '/product'), child: const Text('跳转到商品页面'), ), ElevatedButton( // 命名路由跳转 onPressed: () => Navigator.pushNamed(context, '/product/1'), child: const Text('商品1'), ), ElevatedButton( // 命名路由跳转 onPressed: () => Navigator.pushNamed(context, '/product/2'), child: const Text('商品2'), ), // 未知路由跳转 ElevatedButton( // 命名路由跳转 onPressed: () => Navigator.pushNamed(context, '/product222'), child: const Text('跳转到不存在的路由'), ), ], ), ); } } // 商品 class Product extends StatelessWidget { const Product({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('商品页面'), ), body: Container( padding: const EdgeInsets.all(10), child: ElevatedButton( onPressed: () { return Navigator.pop(context); }, child: const Text('返回'), ), ), ); } } // 商品详情 class ProductDetail extends StatelessWidget { final String id; const ProductDetail({ Key? key, required this.id, }) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('商品详情'), ), body: ListView( padding: const EdgeInsets.all(10), children: [ Text('当前商品的id是 $id'), ElevatedButton( onPressed: () { return Navigator.pop(context); }, child: const Text('返回'), ), ], ), ); } } // 404 class UnknownPage extends StatelessWidget { const UnknownPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('404'), ), body: Container( padding: const EdgeInsets.all(10), child: const Text('页面飞到太空去了……'), ), ); } }