前言
再讲导航与路由之前,我们需要了解一个知识点 MaterialApp
关于 MaterialApp 导航配置的执行顺序
home -> route -> onGenerateRoute -> onUnknownRoute
Navigator
一个小部件,用于管理具有堆栈规则的一组子小部件。
这篇文章讲的是静态路由 。下次在补充动态路由的知识点
许多应用程序在其窗口小部件层次结构的顶部附近有一个导航器,以便使用叠加显示其逻辑历史记录,最近访问过的页面可视化地显示在旧页面之上。使用此模式,导航器可以通过在叠加层中移动小部件来直观地从一个页面转换到另一个页面。类似地,导航器可用于通过将对话框窗口小部件放置在当前页面上方来显示对话框。
在Flutter中,这些元素称为路径,它们由Navigator小部件管理。导航器管理一堆Route对象,并提供管理堆栈的方法,如Navigator.push和Navigator.pop。
接下来看下如何是navigator
首先注册相关路由页面
移动应用程序通常管理大量路由,通常最容易通过名称引用它们。按照惯例,路径名称使用类似路径的结构(例如,'/ a / b / c')。应用程序的主页路由默认名为“/”。
该MaterialApp可以用创建Map<String, WidgetBuilder>从一个路径名映射到一个生成器功能,将创建它。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
routes: <String, WidgetBuilder>{
"/nameRoute": (BuildContext context) => new SecondPage(),
'/a': (BuildContext context) => new MyPage(title: 'A 页面'),
'/b': (BuildContext context) => new MyPage(title: 'B 页面'),
'/c': (BuildContext context) => new MyPage(title: 'C 页面'),
},
);
}
}
创建了相应的路由之后,看下如何去跳转 ,以下两种写法都可以
Navigator.pushNamed(context, "/nameRoute");
Navigator.of(context).pushNamed('/nameRoute');
//当然也可以传参
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new DetailScreen(todo: new Todo("哈哈","嘻嘻")),
),
);
跳转到相应页面之后
需要回退当上一个界面
Navigator.pop(context);
//如果上一个页面需要去到下一个页面传回来的值
//第一个页面
Navigator.push<String>(context,
new MaterialPageRoute(builder: (BuildContext context) {
return new ThirdPage(title: "请输入昵称");
})).then((String result) {
showDialog(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
content: new Text("您输入的昵称为:$result"),
);
});
});
//第二个页面
Navigator.pop(context, params);
以下贴出完整代码 跑一跑就有更深的理解了
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class Todo {
final String title;
final String description;
Todo(this.title, this.description);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
routes: <String, WidgetBuilder>{
"/nameRoute": (BuildContext context) => new SecondPage(),
'/a': (BuildContext context) => new MyPage(title: 'A 页面'),
'/b': (BuildContext context) => new MyPage(title: 'B 页面'),
'/c': (BuildContext context) => new MyPage(title: 'C 页面'),
},
);
}
}
class MyPage extends StatelessWidget {
MyPage({Key key, this.title}) : super(key: key);
final String title;
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text(title)),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("演示跳转"),
),
body: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new FlatButton(
onPressed: () {
print("点击跳转啊");
Navigator.pushNamed(context, "/nameRoute");
// Navigator.of(context).pushNamed('/nameRoute');
},
child: new Text("直接使用name跳转")),
new FlatButton(
onPressed: () {
Navigator.push<String>(context,
new MaterialPageRoute(builder: (BuildContext context) {
return new ThirdPage(title: "请输入昵称");
})).then((String result) {
showDialog(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
content: new Text("您输入的昵称为:$result"),
);
});
});
},
child: new Text("跳转传参并返回值")),
new RaisedButton(
child: new Text('A按钮'),
onPressed: () {
// Navigator.of(context).pushNamed('/a');
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new DetailScreen(todo: new Todo("哈哈","嘻嘻")),
),
);
},
),
new RaisedButton(
child: new Text('B按钮'),
onPressed: () {
Navigator.of(context).pushNamed('/b');
},
),
new RaisedButton(
child: new Text('C按钮'),
onPressed: () {
Navigator.of(context).pushNamed('/c');
},
)
],
),
),
);
}
}
class DetailScreen extends StatelessWidget {
// Declare a field that holds the Todo
final Todo todo;
// In the constructor, require a Todo
DetailScreen({Key key, @required this.todo}) : super(key: key);
@override
Widget build(BuildContext context) {
// Use the Todo to create our UI
return new Scaffold(
appBar: new AppBar(
title: new Text("${todo.title}"),
),
body: new Padding(
padding: new EdgeInsets.all(16.0),
child: new Text('${todo.description}'),
),
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("第二页"),
),
body: new Center(
child: new FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: new Text("return")),
),
);
}
}
class ThirdPage extends StatefulWidget {
final String title;
ThirdPage({this.title});
@override
State<StatefulWidget> createState() {
return new _ThirdPageState();
}
}
class _ThirdPageState extends State<ThirdPage> {
TextEditingController controller;
@override
void initState() {
controller = new TextEditingController();
super.initState();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Column(
children: <Widget>[
new TextField(
decoration: new InputDecoration(labelText: "请输入昵称"),
controller: controller,
),
new RaisedButton(
color: Colors.blueAccent,
onPressed: () {
if (controller.text == '') {
showDialog(
context: context,
builder: (BuildContext context) => new AlertDialog(
title: new Text("请输入昵称"),
));
return;
}
Navigator.pop(context, controller.text);
},
child: new Text("OK"))
],
),
);
}
}