Oftentimes, we not only want to navigate to a new screen, but also pass somedata to the screen as well. For example, we often want to pass information aboutthe item we tapped on.

Remember: Screens are Just Widgets™. In this example, we’ll create a Listof Todos. When a todo is tapped on, we’ll navigate to a new screen (Widget) thatdisplays information about the todo.

Directions

  • Define a Todo class
  • Display a List of Todos
  • Create a Detail Screen that can display information about a todo
  • Navigate and pass data to the Detail Screen

1. Define a Todo class

First, we’ll need a simple way to represent Todos. For this example, we’llcreate a class that contains two pieces of data: the title and description.

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

2. Create a List of Todos

Second, we’ll want to display a list of Todos. In this example, we’ll generate20 todos and show them using a ListView. For more information on working withLists, please see the Basic List recipe.

Generate the List of Todos

  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. );

Display the List of Todos using a ListView

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

So far, so good. We’ll generate 20 Todos and display them in a ListView!

3. Create a Detail Screen that can display information about a todo

Now, we’ll create our second screen. The title of the screen will contain thetitle of the todo, and the body of the screen will show the description.

Since it’s a normal StatelessWidget, we’ll simply require that users creatingthe Screen pass through a Todo! Then, we’ll build a UI using the given 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 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. Navigate and pass data to the Detail Screen

With our DetailScreen in place, we’re ready to perform the Navigation! In ourcase, we’ll want to Navigate to the DetailScreen when a user taps on a Todo inour List. When we do so, we’ll also want to pass the Todo to the DetailScreen.

To achieve this, we’ll write anonTapcallback for our ListTile Widget. Within our onTap callback, we’ll onceagain employ the Navigator.pushmethod.

  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. );

Complete example

  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