詳解flutter如何實現(xiàn)局部導(dǎo)航管理
引言
今天,小編給大家分享如何在 flutter 中實現(xiàn) ‘局部導(dǎo)航’。開始之前我們先來統(tǒng)一一下關(guān)于 局部導(dǎo)航 的概念。
局部導(dǎo)航是什么?
我們在 flutter 中使用 navigator 來管理 app 的頁面堆棧,主要包括 push、pop 這兩種操作。而當(dāng)我們UI設(shè)計劃分得更細(xì)致時,可能遇到需要在某個獨立頁面里,單獨維護(hù)一套子級的堆棧管理。這就叫 局部導(dǎo)航管理。
局部控件內(nèi)單獨維護(hù)局部范圍內(nèi)的堆棧管理的形式有很多,例如:
- 形式一: 左側(cè)是菜單欄,右側(cè)是內(nèi)容塊,在內(nèi)容塊中單獨維護(hù)局部的頁面push、pop、操作。
- 形式二:dialog 彈窗中單獨維護(hù)布局堆棧管理。
那么下面,小編使用 dialog 的形式來分享實現(xiàn)過程。
實現(xiàn)步驟
第一步
創(chuàng)建工具類,用于局部導(dǎo)航管理,思想是:將需要單獨進(jìn)行堆棧管理的頁面使用新的子級 navigator 進(jìn)行包裹,單獨維護(hù)一個 navigator,做到每個堆棧容器實現(xiàn)內(nèi)部各自管理。
///工具類:用于局部導(dǎo)航管理 class LocalNavigator extends StatelessWidget { final Widget child; const LocalNavigator(this.child, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Navigator( initialRoute: '/', onGenerateRoute: (settings) { return MaterialPageRoute( settings: const RouteSettings(name: '/'), builder: (context) { return child; }, ); }, ); } }
第二步
如上 demo 示例,實現(xiàn)一個單獨堆棧管理的彈窗內(nèi)部,對彈窗方法進(jìn)行封裝處理。
在 showDialog
時使用我們封裝的工具類 LocalNavigator
作為父節(jié)點,對具體子頁面節(jié)點進(jìn)行包裹。
那么子頁面內(nèi)的堆棧操作(push 、pop、)都會在我們的 LocalNavigator 堆棧中響應(yīng)。
/// 通過局部導(dǎo)航開啟一個彈窗 static Future<T?> showLocalDialog<T>( BuildContext context, Widget child, ) { return showDialog<T?>( context: context, builder: (context) { return Dialog( child: SizedBox( width: 200, height: 300, child: LocalNavigator(child), ), ); }, ); }
第三步
彈出 dialog,附上 demo 樣例的完整代碼
void main() { runApp(const Material( child: MyApp(), )); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('demo'), ), body: StatefulBuilder( builder: (context, setState) { return Center( child: TextButton( child: const Text('打開彈窗'), onPressed: () { showLocalDialog<String?>(context, const _PageA()) .then( (data) { //接收來自 dialog 的回調(diào)數(shù)據(jù) if (data != null) { Fluttertoast.showToast(msg: 'mainPage 接收數(shù)據(jù):$data'); } }, ); }, ), ); }, ), ), ); } } class _PageA extends StatelessWidget { const _PageA({Key? key}) : super(key: key); void jumpPageB(BuildContext context) { Navigator.push<String?>( context, MaterialPageRoute( builder: (context) => const _PageB(), ), ).then( (data) { if (data != null) { //接收來自 pageB 的回調(diào)數(shù)據(jù) Fluttertoast.showToast(msg: 'pageA 接收數(shù)據(jù):$data'); } }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('PageA')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( onPressed: () { jumpPageB(context); }, child: const Text('跳轉(zhuǎn)頁面B'), ), ], ), ), ); } } class _PageB extends StatelessWidget { const _PageB({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('PageB')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( onPressed: () { Navigator.of(context).pop('我是來自pageB的數(shù)據(jù)'); }, child: const Text('返回pageA'), ), const SizedBox(height: 20), TextButton( onPressed: () { Navigator.of(context, rootNavigator: true).pop('我是來自pageC的數(shù)據(jù)'); }, child: const Text('關(guān)閉整個彈窗'), ), ], ), ), ); } }
技術(shù)點分析:
1. 局部 Navigator 管理重點
將 需要維護(hù)局部堆棧關(guān)系的子節(jié)點 進(jìn)行嵌套,使用自定義的工具類 LocalNavigator
作為父節(jié)點。
2. 返回上一級頁面,與關(guān)閉整個彈窗怎么區(qū)分?
關(guān)鍵點在于 Navigator.of(context)
中的 rootNavigator
可選入?yún)?,默認(rèn)是不使用根節(jié)點下的 navigator。
- 返回上一級頁面,使用當(dāng)前的堆棧進(jìn)行操作
Navigator.of(context).pop()
- 關(guān)閉整個彈窗,意味著在根堆棧進(jìn)行 pop 操作
Navigator.of(context, rootNavigator: true).pop()
3. 如何接收頁面關(guān)閉時回傳的數(shù)據(jù)?
- 關(guān)閉時通過 pop() 方法進(jìn)行數(shù)據(jù)回傳
Navigator.of(context).pop(data)
- 接收回傳數(shù)據(jù),在打開新堆棧的 push 方法中接收回返回值
Navigator.push<T?>(context, route).then((T){ })
T 為返回值的泛型標(biāo)識,注意在接收處理的地方需要對返回值進(jìn)行判空操作
Navigator.push<String?>( context, MaterialPageRoute( builder: (context) => const _PageB(), ), ).then( (data) { if (data != null) { //接收來自 pageB 的回調(diào)數(shù)據(jù) Fluttertoast.showToast(msg: 'pageA 接收數(shù)據(jù):$data'); } }, );
以上就是詳解flutter如何實現(xiàn)局部導(dǎo)航管理的詳細(xì)內(nèi)容,更多關(guān)于flutter局部導(dǎo)航管理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android自定義View實現(xiàn)帶音效和震動的SeekBar
這篇文章主要為大家詳細(xì)介紹了Android如何自定義View實一個帶音效和震動的SeekBar,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03Android?配合Mat工具監(jiān)聽查找內(nèi)存泄漏的操作方法
這篇文章主要介紹了Android?配合Mat工具監(jiān)聽查找內(nèi)存泄漏問題,使用Android Studio Profiler查看內(nèi)存的操作,本文通過圖文實例相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05Android studio 使用Debugger問題(代碼中含有ndk)
這篇文章主要介紹了Android studio 使用Debugger問題(代碼中含有ndk),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11android導(dǎo)入第三方j(luò)ar包報錯 如何正確導(dǎo)入jar包
怎樣在android平臺上使用第三方j(luò)ar包,為什么我在引入了,編譯時沒有錯誤,運行時就有錯誤,報無法實例化錯誤,請問這是什么原因,本文給于解決方法,需要了解的朋友可以參考下2012-12-12Android自定義View實現(xiàn)數(shù)字雨效果的全過程
小時候看時印象最深的就是數(shù)字雨了,導(dǎo)致我現(xiàn)在寫代碼也要是黑屏,下面這篇文章主要給大家介紹了關(guān)于Android自定義View實現(xiàn)數(shù)字雨效果的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02說說在Android如何使用服務(wù)(Service)的方法
這篇文章主要介紹了說說在Android如何使用服務(wù)(Service)的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06Android TextView和ImageView簡單說明
Android TextView和ImageView簡單說明,需要的朋友可以參考一下2013-03-03