從一些簡單的 push 技巧,到 routes 設置,最後使用 fluro 來控制 App 整體頁面流程。
Other great relative articles:
如果你想要跳到 Page A 再跳回 Page B 時
在 Page A 使用 push 語法
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageB()),
);
並在 Page B 使用 pop 語法
onPressed: () {
Navigator.pop(context);
}
當你想要從 Page A 傳送資料到 Page B 來使用時
先定義好 Page B 要接收的資料
class PageB extends StatelessWidget {
final String title;
// In the constructor, require a title.
PageB({Key key, @required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
);
}
}
在 Page A 就可以輕鬆傳過去
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageB(title: 'Hello')),
);
當你想要把 Page B 的某些結果,在返回時一併給 Page A 時
Page A 利用 await 方式等待 Page B 的結果
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageB()),
);
在 PageB 定義好 pop 的 result 即可
Navigator.pop(context, 'Here is my result');
最後就可以在 Page A 使用該 result
如果你在建構大專案時,有非常多的 page 需要 navigate,你可以使用內建的 named route 方法,來避免太多的 push code duplication。
建立好 named route 後,只要使用 Navigator.pushNamed()
就可以快速跳轉到定義好的頁面。
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => PageA(),
'/pageb': (context) => PageB(),
'/pagec': (context) => PageC(),
},
);
❗ 要注意的是,一但定義好 initialRoute 的頁面,就不需要在定義 home 了 ❗
接著在 app 的任何地方,只要使用 pushNamed 即可移動到定義好的 page
Navigator.pushNamed(context, '/pageb');
在 Page B 指定要接收的資料類型,使用 ModalRoute.of().settings.arguments
來取得。
在這個例子中,String 可以取代成任何你想傳的類型。
@override
Widget build(BuildContext context) {
// Extract the arguments from the current ModalRoute settings and cast them
final String args = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text('Page B'),
),
body: Center(
child: Text(
'$args',
style: Theme.of(context).textTheme.display1,
),
));
}
Page A 即可使用 pushNamed 給予的 arguments 來指定傳送資料
String args = 'Extract';
Navigator.pushNamed(context, '/pageb', arguments: args);
利用常態方式接收 arguments,不在此使用 ModalRoute
來取得值
class PageC extends StatelessWidget {
final String content;
PageC({this.content});
...
}
而是在 MaterialApp 先定義好 onGenerateRoute
,並以此來指定當 push 時傳送資料
onGenerateRoute: (settings) {
if (settings.name == '/pagec') {
final String args = settings.arguments;
return MaterialPageRoute(
builder: (context) => PageC(
content: args,
));
}
}
同樣方式傳送即可
String args = 'Pass';
Navigator.pushNamed(context, '/pagec', arguments: args);
這邊有範例程式碼: My Example Code
Fluro 是一個管理 route 以及便利化 navigation 的 third library ,不但支援內建 routes 外,還有各式各樣容易使用的 function。
首先在 app 初始化好 Router,官方建議可以設定一個 static/global 變數來存取這個 Router
final router = Router();
Application.router = router;
定義需要使用到的 Route Handler
var userHandler = Handler(handlerFunc: (context, params) => UserScreen());
再來用初始化好的 Router 定義每個 namedRoutes 對應的 handler
static String user = '/user';
router.define(user, handler: userHandler);
回到 MaterialApp 給予 onGenerateRoute 值
return MaterialApp(
title: 'Fluro Demo',
onGenerateRoute: Application.router.generator,
);
如此一來就可以在 App 的任何地方使用 navigation
router.navigateTo(context, "/user");
先在接收頁面定義好接收的參數與其類型
class PageB extends StatelessWidget {
final String message;
PageB({this.message});
...
}
在 Handler 透過 params 得到傳遞值
var pageBHandler = Handler(handlerFunc: (context, params) {
String message = params["message"][0];
return PageB(
message: message,
);
});
利用類似 http get 的方式指定參數給接收頁面
final message = 'Hello';
Application.router.navigateTo(context, "/page_b?message=$message");
navigateTo 有提供多種內建的 transition,但也可以使用 custom 來自訂
Application.router.navigateTo(context, '/page_c',
// this transition will override the transition from router.define !
transition: TransitionType.custom,
transitionDuration: Duration(milliseconds: 500),
transitionBuilder: (context, anim, secAnim, child) {
return ScaleTransition(
scale: anim,
child: RotationTransition(
turns: anim,
child: child,
),
);
});
跟 return data from screen 的方法一樣
只要定義好 await function 來取得 navigateTo 返回的 Future<dynamic>
即可
final result = await Application.router.navigateTo(context, '/page_d');
if (result != null)
_scaffoldKey.currentState
..removeCurrentSnackBar()
..showSnackBar(SnackBar(content: Text('Result: $result')));
在下一頁的 pop 返回 result 即可
Navigator.pop(context, 'hello');
這邊有範例程式碼: My Example Code