在开发的过程中,我们经常需要在跳转到新页面的时候,能同时传递一些数据。比如,传递用户点击的元素信息。

还记得么,全屏的界面也只是 Widget。在这个例子中,我们会创建一个待办事项列表, 当某个事项被点击的时候,会跳转到新的一屏 (Widget),在新的一屏显示待办事项的详细信息。

步骤

  • 定义一个描述待办事项的数据类

  • 用列表 (List Widget) 显示待办事项

  • 创建一个显示待办事项详细信息的界面

  • 传递数据并跳转到待办事项详细信息界面

1. 定义一个描述待办事项的数据类

首先,我们需要一个简单的方式来描述待办事项。我们创建一个类叫做 Todo,包含 titledescription 两个成员变量。

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

2. 创建待办事项列表

第二步,我们需要显示一个待办事项列表,生成 20 条待办事项并用 ListView 显示。如果你想了解更多关于列表显示的内容,请阅读文档 基础列表

生成待办事项列表

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

用 ListView 显示待办事项列表

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

到目前为止, 我们生成了 20 条待办事项, 并用 ListView 把它显示出来了。

3. 创建一个显示待办事项详细信息的界面

现在,我们来创建第二个全屏的界面, 界面的标题是待办事项的标题, 界面下面显示待办事项的描述信息。

这个界面是一个 StatelessWidget,创建的时需要传递 Todo 对象给它, 它就可以使用传给他的 Todo 对象来构建 UI 。

  1. class DetailScreen extends StatelessWidget {
  2. // 声明一个成员变量来保存 Todo 对象 (Declare a field that holds the Todo)
  3. final Todo todo;
  4. // 构造函数需要 Todo 对象 (In the constructor, require a Todo)
  5. DetailScreen({Key key, @required this.todo}) : super(key: key);
  6. @override
  7. Widget build(BuildContext context) {
  8. // 使用 Todo 对象构建 UI (Use the Todo to create our UI)
  9. return Scaffold(
  10. appBar: AppBar(
  11. title: Text(todo.title),
  12. ),
  13. body: Padding(
  14. padding: EdgeInsets.all(16.0),
  15. child: Text(todo.description),
  16. ),
  17. );
  18. }
  19. }

4. 传递数据并跳转到待办事项详细信息界面

上面写完了 DetailScreen ,现在该执行界面跳转啦!我们想让用户在点击列表中的某个待办事项时跳转到 DetailScreen 界面,同时能传递点击的这条代办事项对象(Todo 对象) 。

想要实现这些,我们来编写 ListTile widget 的 onTap 回调函数,继续使用 Navigator.push 方法。

  1. ListView.builder(
  2. itemCount: todos.length,
  3. itemBuilder: (context, index) {
  4. return ListTile(
  5. title: 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 DetailScreen, we're
  8. // also passing the current todo to it!
  9. onTap: () {
  10. Navigator.push(
  11. context,
  12. MaterialPageRoute(
  13. builder: (context) => 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(MaterialApp(
  10. title: 'Passing Data',
  11. home: TodosScreen(
  12. todos: List.generate(
  13. 20,
  14. (i) => 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 Scaffold(
  28. appBar: AppBar(
  29. title: Text('Todos'),
  30. ),
  31. body: ListView.builder(
  32. itemCount: todos.length,
  33. itemBuilder: (context, index) {
  34. return ListTile(
  35. title: 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 DetailScreen, we're
  38. // also passing the current todo through to it!
  39. onTap: () {
  40. Navigator.push(
  41. context,
  42. MaterialPageRoute(
  43. builder: (context) => 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 Scaffold(
  62. appBar: AppBar(
  63. title: Text(todo.title),
  64. ),
  65. body: Padding(
  66. padding: EdgeInsets.all(16.0),
  67. child: Text(todo.description),
  68. ),
  69. );
  70. }
  71. }

Passing Data Demo