在 Flutter 中路由也是主要用来处理页面跳转、页面数据传递等操作。Flutter 的路由主要通过路由(Route)和导航器(Navigator)配合使用。Navigator 主要负责路由页面的堆栈管理和操作,例如添加跳转页面、移除页面等。
在 Flutter 中路由用法主要有两种用法:一种是在 MaterialApp 里的 routes 参数里配置定义好路由列表,也就是提前定义好要跳转的页面和名称。
Map<String, WidgetBuilder> routes;
先定义路由跳转路径:
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: ShowAppPage(),
// 定义路由表
routes: <String, WidgetBuilder>{
'/buttonpage': (BuildContext context) {
return ButtonSamples();
},
'/routepage': (BuildContext context) {
return RouteSamples();
},
},
);
// 当然,为了简洁,我们可以用lambda简写路由注册
routes: <String, WidgetBuilder>{
'/buttonpage': (BuildContext context) => ButtonSamples(),
'/routepage': (BuildContext context) => RouteSamples(),
},
主要规则就是前面定义一个路由页面名称,后面定义路径。
接下来就是通过这个名称来执行跳转,这里就要用到 Navigator 了。
…
body: Center(
child: FlatButton(
child: Text("路由跳转"),
onPressed: () {
// 通过之前定义的名字来执行跳转
Navigator.of(context).pushNamed("buttonpage");
},
),
)
Navigator 继承自 StatefulWidget,构造如下:
const Navigator({
Key key,
// 默认路由
this.initialRoute,
// 通用路由跳转规则
@required this.onGenerateRoute,
// 未知路由
this.onUnknownRoute,
// 路由的观察者,监听
this.observers = const <NavigatorObserver>[]
})
Navigator 的主要方法如下。
接下来我们来看 Flutter 中 Navigator 和 Route 基本用法。
Navigator 之前介绍了,Route 在 Flutter 中主要有两种实现方法:一个是使用 MaterialPageRoute;另一个是使用 PageRouteBuilder 来构建。
MaterialPageRoute 构造方法:
MaterialPageRoute({
// 构建页面
@required this.builder,
// 路由设置
RouteSettings settings,
// 是否保存页面状态、内容
this.maintainState = true,
bool fullscreenDialog = false,
})
PageRouteBuilder 构造方法:
PageRouteBuilder({
// 路由设置
RouteSettings settings,
// 目标页面
@required this.pageBuilder,
// 跳转过度动画设置
this.transitionsBuilder = _defaultTransitionsBuilder,
this.transitionDuration = const Duration(milliseconds: 300),
this.opaque = true,
this.barrierDismissible = false,
this.barrierColor,
this.barrierLabel,
this.maintainState = true,
})
PageRouteBuilder 构建的路由可以设置跳转动画效果。
我们通过代码实例来看下这两种基本用法:
FlatButton(
child: Text("路由跳转"),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (BuildContext context) {
return ButtonSamples();
}));
},
);
MaterialPageRoute 无须预先配置好路由目标页面和名称,比较的灵活,也可以传递参数。
Navigator.push(context, PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return ButtonSamples();
},
transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: RotationTransition(
turns: Tween<double>(begin: 0.5, end: 1.0).animate(animation),
child: child,// 这里的child是pageBuilder里返回的目标页面
),
);
}
));
PageRouteBuilder 可以创建一个更加丰富复杂的页面路由跳转,可以设置跳转动画。
好,最后在看一个复杂一些的情况处理。例如我们有一个首页 Tab 页面,内部有自己的路由跳转,当我们跳转到个人中心时候,需要判断是否登录,没有登录就跳到登录页,登录过就直接显示个人中心信息。这种就是路由里面的内部还有一个自己的路由。这就需要我们用 Navigator 里的 RouteSettings 了,我们看下实现方法:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (BuildContext context) => HomePage(),
// 登录页
'/signup': (BuildContext context) => SignUpPage(),
},
);
}
}
class SignUpPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// SignUpPage有自己的内部路由
return Navigator(
// 默认路由页面
initialRoute: 'signup/personal_info',
// 内部路由的跳转处理
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
switch (settings.name) {
case 'signup/personal_info':
builder = (BuildContext _) => CollectPersonalInfoPage();
break;
case 'signup/choose_credentials':
builder = (BuildContext _) => ChooseCredentialsPage();
break;
default:
throw Exception('Invalid route: ${
settings.name}');
}
return MaterialPageRoute(builder: builder, settings: settings);
},
);
}
}
接下来我们学习路由页面跳转并且传递参数的实现方法。
页面跳转传递参数,这里建议使用动态路由,而不是使用在 MaterialApp 的 routes 属性里静态定义的这种。
我们先看静态定义的传参用法:
// 通过key,value传参
Navigator.pushNamed(
context,
'/weather',
arguments: <String, String>{
'city': 'Berlin',
'country': 'Germany',
},
);
// 通过Object来传递参数
class WeatherRouteArguments {
WeatherRouteArguments({
this.city, this.country});
final String city;
final String country;
}
Navigator.pushNamed(
context,
'/weather',
arguments: WeatherRouteArguments(city: 'Berlin', country: 'Germany'),
);
// 接收页面通过RouteSettings进行接收参数,比较不灵活和麻烦
MaterialApp(
onGenerateRoute: (RouteSettings settings){
...
settings.arguments
...
},
通常我们通过动态路由传参方式来实现:
Navigator.push(context, new MaterialPageRoute(builder: (BuildContext context){
return new ButtonSamples(
title:'标题',
name:'名称'
);
}))
...
// 第二个页面构造方法里接收参数
class ButtonSamples extends StatefulWidget {
String title;
String name;
ButtonSamples({
Key key, this.title, this.name}) : super(key: key);
@override
State<StatefulWidget> createState() {
return ButtonSamplesState();
}
}
或者,也可以传递一个 Object 对象:
class Book{
String title;
String name;
Book({
this.title, this.name});
}
Navigator.push(context, new MaterialPageRoute(builder: (BuildContext context){
return new ButtonSamples(Book
title:'标题',
name:'名称'
);
}))
// 第二个页面构造方法里接收参数
class ButtonSamples extends StatefulWidget {
Book book;
ButtonSamples({
Key key, this.book}) : super(key: key);
@override
State<StatefulWidget> createState() {
return ButtonSamplesState();
}
}
接下来是关闭页面返回数据和上一个页面接收返回数据的用法:
// 关闭页面返回数据
Navigator.pop(context, '返回数据');
// 接收返回数据
Navigator.push<String>(context,
MaterialPageRoute(builder: (BuildContext context) {
return ButtonSamples(title: '标题', name: '名称');
})).then((String result) {
//处理代码
});
路由效果如图:
本节博客主要是给大家讲解了 Flutter 的路由基础知识和页面跳转传参用法和特点。