通常,我们不仅要导航到新的页面 ,还要将一些数据传给页面。例如,我们想传一些关于我们点击的条目的信息。
请记住:页面只是Widgets™。在这个例子中,我们将创建一个Todos列表。当点击一个todo时,我们将导航到一个显示关于待办事项信息的新页面 (Widget)。
Directions
- 定义一个Todo类。
- 显示Todos列表。
- 创建一个显示待办事项详情的页面。
- 导航并将数据传递到详情页。
1. 定义一个 Todo 类
首先,我们需要一种简单的方法来表示Todos(待办事项)。在这个例子中,我们将创建一个包含两部分数据的类:标题和描述。
class Todo {final String title;final String description;Todo(this.title, this.description);}
2. 创建一个Todos列表
其次,我们要显示一个Todos列表。在这个例子中,我们将生成20个待办事项并使用ListView显示它们。有关使用列表的更多信息,请参阅基础 List。
生成Todos列表
final todos = new List<Todo>.generate(20,(i) => new Todo('Todo $i','A description of what needs to be done for Todo $i',),);
使用ListView显示Todos列表
new ListView.builder(itemCount: todos.length,itemBuilder: (context, index) {return new ListTile(title: new Text(todos[index].title),);},);
到现在为止,我们生成了20个Todo并将它们显示在ListView中!
3. 创建一个显示待办事项(todo)详情的页面
现在,我们将创建我们的第二个页面 。页面的标题将包含待办事项的标题,页面正文将显示说明。
由于这是一个普通的StatelessWidget,我们只需要在创建页面时传递一个Todo!然后,我们将使用给定的Todo来构建新的页面。
class DetailScreen extends StatelessWidget {// Declare a field that holds the Todofinal Todo todo;// In the constructor, require a TodoDetailScreen({Key key, @required this.todo}) : super(key: key);@overrideWidget build(BuildContext context) {// Use the Todo to create our UIreturn new Scaffold(appBar: new AppBar(title: new Text("${todo.title}"),),body: new Padding(padding: new EdgeInsets.all(16.0),child: new Text('${todo.description}'),),);}}
4. 导航并将数据传递到详情页
接下来,当用户点击我们列表中的待办事项时我们将导航到DetailScreen,并将Todo传递给DetailScreen。
为了实现这一点,我们将实现ListTile的onTap回调。
在我们的onTap回调中,我们将再次调用Navigator.push方法。
new ListView.builder(itemCount: todos.length,itemBuilder: (context, index) {return new ListTile(title: new Text(todos[index].title),// When a user taps on the ListTile, navigate to the DetailScreen.// Notice that we're not only creating a new DetailScreen, we're// also passing the current todo to it!onTap: () {Navigator.push(context,new MaterialPageRoute(builder: (context) => new DetailScreen(todo: todos[index]),),);},);},);
完整的例子
import 'package:flutter/foundation.dart';import 'package:flutter/material.dart';class Todo {final String title;final String description;Todo(this.title, this.description);}void main() {runApp(new MaterialApp(title: 'Passing Data',home: new TodosScreen(todos: new List.generate(20,(i) => new Todo('Todo $i','A description of what needs to be done for Todo $i',),),),));}class TodosScreen extends StatelessWidget {final List<Todo> todos;TodosScreen({Key key, @required this.todos}) : super(key: key);@overrideWidget build(BuildContext context) {return new Scaffold(appBar: new AppBar(title: new Text('Todos'),),body: new ListView.builder(itemCount: todos.length,itemBuilder: (context, index) {return new ListTile(title: new Text(todos[index].title),// When a user taps on the ListTile, navigate to the DetailScreen.// Notice that we're not only creating a new DetailScreen, we're// also passing the current todo through to it!onTap: () {Navigator.push(context,new MaterialPageRoute(builder: (context) => new DetailScreen(todo: todos[index]),),);},);},),);}}class DetailScreen extends StatelessWidget {// Declare a field that holds the Todofinal Todo todo;// In the constructor, require a TodoDetailScreen({Key key, @required this.todo}) : super(key: key);@overrideWidget build(BuildContext context) {// Use the Todo to create our UIreturn new Scaffold(appBar: new AppBar(title: new Text("${todo.title}"),),body: new Padding(padding: new EdgeInsets.all(16.0),child: new Text('${todo.description}'),),);}}
