學習
https://flutter.cn/docs/development/ui/navigation
https://flutter.cn/docs/cookbook/navigation/returning-data
從一個頁面回傳數據
在某些場景下,我們需要在回退到上一屏時同時返回一些數據。比如,我們跳轉到新的一屏,有兩個選項讓用戶選擇,當用戶點擊某個選項後會返回到第一屏,同時在第一屏可以知道用戶選擇的信息。
你可以使用
Navigator.pop()
來進行以下步驟:
感覺類似於Android的startActivityForResult + setResult + onActivityResult
步驟
-
創建主屏界面
-
添加按鈕,點擊時跳轉到選擇界面
-
在選擇界面顯示兩個按鈕
-
當任意一個按鈕被點擊,關閉選擇界面回退到主屏界面
-
在主屏界面顯示 snackbar ,展示選中的項目
1. 創建主屏界面
主屏界面顯示一個按鈕,當點擊按鈕時跳轉到選擇界面。
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Returning Data Demo'),
),
// Create the SelectionButton widget in the next step.
body: Center(child: SelectionButton()),
);
}
}
2. 添加按鈕,點擊時跳轉到選擇界面
接下來,我們創建 SelectionButton 按鈕,它有兩個功能:
-
點擊時跳轉到選擇界面
-
等待選擇界面給它返回結果
class SelectionButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
_navigateAndDisplaySelection(context);
},
child: Text('Pick an option, any option!'),
);
}
// A method that launches the SelectionScreen and awaits the
// result from Navigator.pop.
_navigateAndDisplaySelection(BuildContext context) async {
// Navigator.push returns a Future that completes after calling
// Navigator.pop on the Selection Screen.
final result = await Navigator.push(
context,
// Create the SelectionScreen in the next step.
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
}
}
3. 在選擇界面顯示兩個按鈕
現在來構建選擇界面,它包含兩個按鈕,當任意一個按鈕被點擊的時候,關閉選擇頁面回退到主屏界面,並讓主屏界面知道哪個按鈕被點擊了。
這一步我們來定義 UI,在下一步完成數據的返回。
class SelectionScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pick an option'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: () {
// 在這裏返回 "Yep" (Pop here with "Yep"...)
},
child: Text('Yep!'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: () {
// 在這裏返回 "Nope" (Pop here with "Nope")
},
child: Text('Nope.'),
),
)
],
),
),
);
}
}
4. 當任意一個按鈕被點擊,關閉選擇界面回退到主屏界面
接下來我們來更新兩個按鈕的 onPressed()
回調函數,使用 Navigator.pop()
回退界面並返回數據給主屏界面。 Navigator.pop()
方法可以接受第二個參數 result
,它是可選的,如果傳遞了 result
,數據將會通過 Future
方法的返回值傳遞。
Yep 按鈕
RaisedButton(
onPressed: () {
// The Yep button returns "Yep!" as the result.
Navigator.pop(context, 'Yep!');
},
child: Text('Yep!'),
);
Nope 按鈕
RaisedButton(
onPressed: () {
// The Nope button returns "Nope!" as the result.
Navigator.pop(context, 'Nope!');
},
child: Text('Nope!'),
);
5. 在主屏界面顯示一個 snackbar,展示選中的項目
現在,我們跳轉到選擇界面並等待返回結果,當結果返回時我們可以做些事情。
在本例中,我們用一個 snackbar 顯示結果,我們來更新 SelectionButton
類中的 _navigateAndDisplaySelection()
方法。
_navigateAndDisplaySelection(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
// After the Selection Screen returns a result, hide any previous snackbars
// and show the new result.
// 等選擇界面返回結果,先隱藏之前的 snackbars,結果顯示在新的 snackbars 裏 (After the Selection Screen returns a result, hide any previous snackbars and show the new result!)
Scaffold.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(content: Text("$result")));
}
整段代碼下面鏈接中有完整的的實際演示
https://flutter.cn/docs/cookbook/navigation/returning-data
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Returning Data',
home: HomeScreen(),
));
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Returning Data Demo'),
),
body: Center(child: SelectionButton()),
);
}
}
class SelectionButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
_navigateAndDisplaySelection(context);
},
child: Text('Pick an option, any option!'),
);
}
// A method that launches the SelectionScreen and awaits the result from
// Navigator.pop.
_navigateAndDisplaySelection(BuildContext context) async {
// Navigator.push returns a Future that completes after calling
// Navigator.pop on the Selection Screen.
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
// After the Selection Screen returns a result, hide any previous snackbars
// and show the new result.
Scaffold.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(content: Text("$result")));
}
}
class SelectionScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pick an option'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: () {
// Close the screen and return "Yep!" as the result.
Navigator.pop(context, 'Yep!');
},
child: Text('Yep!'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: () {
// Close the screen and return "Nope!" as the result.
Navigator.pop(context, 'Nope.');
},
child: Text('Nope.'),
),
)
],
),
),
);
}
}
總結
感覺類似於Android的startActivityForResult + setResult + onActivityResult
await Navigator.push相對應startActivityForResult + onActivityResult
Navigator.pop 相對應 setResult