通常,我们不仅要导航到新的页面 ,还要将一些数据传给页面。例如,我们想传一些关于我们点击的条目的信息。

请记住:页面只是Widgets™。在这个例子中,我们将创建一个Todos列表。当点击一个todo时,我们将导航到一个显示关于待办事项信息的新页面 (Widget)。

Directions

  1. 定义一个Todo类。
  2. 显示Todos列表。
  3. 创建一个显示待办事项详情的页面。
  4. 导航并将数据传递到详情页。

1. 定义一个 Todo 类

首先,我们需要一种简单的方法来表示Todos(待办事项)。在这个例子中,我们将创建一个包含两部分数据的类:标题和描述。

  1. class Todo {
  2. final String title;
  3. final String description;
  4. Todo(this.title, this.description);
  5. }

2. 创建一个Todos列表

其次,我们要显示一个Todos列表。在这个例子中,我们将生成20个待办事项并使用ListView显示它们。有关使用列表的更多信息,请参阅基础 List

生成Todos列表

  1. final todos = new List<Todo>.generate(
  2. 20,
  3. (i) => new Todo(
  4. 'Todo $i',
  5. 'A description of what needs to be done for Todo $i',
  6. ),
  7. );

使用ListView显示Todos列表

  1. new ListView.builder(
  2. itemCount: todos.length,
  3. itemBuilder: (context, index) {
  4. return new ListTile(
  5. title: new Text(todos[index].title),
  6. );
  7. },
  8. );

到现在为止,我们生成了20个Todo并将它们显示在ListView中!

3. 创建一个显示待办事项(todo)详情的页面

现在,我们将创建我们的第二个页面 。页面的标题将包含待办事项的标题,页面正文将显示说明。

由于这是一个普通的StatelessWidget,我们只需要在创建页面时传递一个Todo!然后,我们将使用给定的Todo来构建新的页面。

  1. class DetailScreen extends StatelessWidget {
  2. // Declare a field that holds the Todo
  3. final Todo todo;
  4. // In the constructor, require a Todo
  5. DetailScreen({Key key, @required this.todo}) : super(key: key);
  6. @override
  7. Widget build(BuildContext context) {
  8. // Use the Todo to create our UI
  9. return new Scaffold(
  10. appBar: new AppBar(
  11. title: new Text("${todo.title}"),
  12. ),
  13. body: new Padding(
  14. padding: new EdgeInsets.all(16.0),
  15. child: new Text('${todo.description}'),
  16. ),
  17. );
  18. }
  19. }

4. 导航并将数据传递到详情页

接下来,当用户点击我们列表中的待办事项时我们将导航到DetailScreen,并将Todo传递给DetailScreen

为了实现这一点,我们将实现ListTileonTap回调。 在我们的onTap回调中,我们将再次调用Navigator.push方法。

  1. new ListView.builder(
  2. itemCount: todos.length,
  3. itemBuilder: (context, index) {
  4. return new ListTile(
  5. title: new Text(todos[index].title),
  6. // When a user taps on the ListTile, navigate to the DetailScreen.
  7. // Notice that we're not only creating a new DetailScreen, we're
  8. // also passing the current todo to it!
  9. onTap: () {
  10. Navigator.push(
  11. context,
  12. new MaterialPageRoute(
  13. builder: (context) => new DetailScreen(todo: todos[index]),
  14. ),
  15. );
  16. },
  17. );
  18. },
  19. );

完整的例子

  1. import 'package:flutter/foundation.dart';
  2. import 'package:flutter/material.dart';
  3. class Todo {
  4. final String title;
  5. final String description;
  6. Todo(this.title, this.description);
  7. }
  8. void main() {
  9. runApp(new MaterialApp(
  10. title: 'Passing Data',
  11. home: new TodosScreen(
  12. todos: new List.generate(
  13. 20,
  14. (i) => new Todo(
  15. 'Todo $i',
  16. 'A description of what needs to be done for Todo $i',
  17. ),
  18. ),
  19. ),
  20. ));
  21. }
  22. class TodosScreen extends StatelessWidget {
  23. final List<Todo> todos;
  24. TodosScreen({Key key, @required this.todos}) : super(key: key);
  25. @override
  26. Widget build(BuildContext context) {
  27. return new Scaffold(
  28. appBar: new AppBar(
  29. title: new Text('Todos'),
  30. ),
  31. body: new ListView.builder(
  32. itemCount: todos.length,
  33. itemBuilder: (context, index) {
  34. return new ListTile(
  35. title: new Text(todos[index].title),
  36. // When a user taps on the ListTile, navigate to the DetailScreen.
  37. // Notice that we're not only creating a new DetailScreen, we're
  38. // also passing the current todo through to it!
  39. onTap: () {
  40. Navigator.push(
  41. context,
  42. new MaterialPageRoute(
  43. builder: (context) => new DetailScreen(todo: todos[index]),
  44. ),
  45. );
  46. },
  47. );
  48. },
  49. ),
  50. );
  51. }
  52. }
  53. class DetailScreen extends StatelessWidget {
  54. // Declare a field that holds the Todo
  55. final Todo todo;
  56. // In the constructor, require a Todo
  57. DetailScreen({Key key, @required this.todo}) : super(key: key);
  58. @override
  59. Widget build(BuildContext context) {
  60. // Use the Todo to create our UI
  61. return new Scaffold(
  62. appBar: new AppBar(
  63. title: new Text("${todo.title}"),
  64. ),
  65. body: new Padding(
  66. padding: new EdgeInsets.all(16.0),
  67. child: new Text('${todo.description}'),
  68. ),
  69. );
  70. }
  71. }