给新页面传值
通常,我们不仅要导航到新的页面 ,还要将一些数据传给页面。例如,我们想传一些关于我们点击的条目的信息。
请记住:页面只是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 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}'),
),
);
}
}
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);
@override
Widget 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 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}'),
),
);
}
}