<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們在flutter中可以使用Navigator.push或者Navigator.pushNamed方法來向Navigator中新增不同的頁面,從而達到頁面調整的目的。
一般情況下這樣已經足夠了,但是有時候我們有多個Navigator的情況下,上面的使用方式就不夠用了。比如我們有一個主頁面app的Navigator,然後裡面有一個匹配好友的功能,這個功能有多個頁面,因為匹配好友功能的多個頁面實際上是一個完整的流程,所以這些頁面需要被放在一個子Navigator中,並和主Navigator區分開。
那麼應該如何處理呢?
主Navigator是我們app的一些主要介面,這裡我們有三個介面,分別是主home介面,一個setting設定介面和好友匹配介面。
其中好友匹配介面包含了三個子介面,這三個子介面將會用到子路由。
先來看下主路由,主路由的情況跟普通的路由沒啥區別,這裡我們首先定義和home和setting匹配的兩個widget:HomePage和SettingsPage:
class HomePage extends StatelessWidget { const HomePage({ super.key, }); @override Widget build(BuildContext context) { return Scaffold( appBar: _buildAppBar(context), body: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( mainAxisSize: MainAxisSize.min, children: const [ SizedBox( width: 250, height: 250, child: Center( child: Icon( Icons.home, size: 175, color: Colors.blue, ), ), ), SizedBox(height: 32), Text( '跳轉到好友匹配頁面', textAlign: TextAlign.center, style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), ], ), ), ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.of(context).pushNamed(routeFriendMatch); }, child: const Icon(Icons.add), ), ); }
HomePage很簡單,它包含了一個floatingActionButton,當點選它的時候會呼叫 Navigator.pushNamed方法進行路由切換。
然後是SettingsPage,它是一個簡單的Column:
class SettingsPage extends StatelessWidget { const SettingsPage({ super.key, }); @override Widget build(BuildContext context) { return Scaffold( appBar: _buildAppBar(), body: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: List.generate(8, (index) { return ListTile( title: Text('設定項$index'), ); }), ), ), ); }
最後一個頁面是FriendMatchFlow,這個頁面比較複雜,我們在下一個再進行講解。
然後我們為主路由在onGenerateRoute方法中進行定義:
void main() { runApp( MaterialApp( onGenerateRoute: (settings) { late Widget page; if (settings.name == routeHome) { page = const HomePage(); } else if (settings.name == routeSettings) { page = const SettingsPage(); } else if (settings.name == routeFriendMatch) { page = const FriendMatchFlow( setupPageRoute: routeFriendMatchPage, ); } return MaterialPageRoute<dynamic>( builder: (context) { return page; }, settings: settings, ); }, debugShowCheckedModeBanner: false, ), ); }
主路由很簡單,跟普通的路由沒有太多的區別。
接下來是構建子路由的步驟。在主路由中,如果路由的名稱是routeFriendMatch,那麼就會跳轉到FriendMatchFlow。
而這個flow頁面實際上是由幾個子頁面組成的:選擇好友頁面,等待頁面,匹配頁面和匹配完畢頁面。
具體的頁面程式碼這裡就不寫了,我們主要來講一下子路由的使用。
對於FriendMatchFlow來說,它本身是一個Navigator,所以我們的build方法是這樣的:
Widget build(BuildContext context) { return WillPopScope( onWillPop: _isExitDesired, child: Scaffold( appBar: _buildFlowAppBar(), body: Navigator( key: _navigatorKey, initialRoute: widget.setupPageRoute, onGenerateRoute: _onGenerateRoute, ), ), ); }
因為他需要根據使用者的不同點選來進行內部路由的切換,所以需要儲存對當前子Navigator的應用,所以這裡FriendMatchFlow是一個StatefulWidget,並且上面的_navigatorKey是一個GlobalKey物件,以提供對子Navigator的參照:
final _navigatorKey = GlobalKey<NavigatorState>();
這裡的_onGenerateRoute方法,跟主路由也是很類似的,主要定義的是子路由中頁面的跳轉:
Route _onGenerateRoute(RouteSettings settings) { late Widget page; switch (settings.name) { case routeFriendMatchPage: page = WaitingPage( message: '匹配附近的好友...', onWaitComplete: _onDiscoveryComplete, ); break; case routeFriendSelectPage: page = SelectFriendPage( onFriendSelected: _onFriendSelected, ); break; case routeFriendConnectingPage: page = WaitingPage( message: '匹配中...', onWaitComplete: _onConnectionEstablished, ); break; case routeFriendFinishedPage: page = FinishedPage( onFinishPressed: _exitSetup, ); break; }
這裡的on***Selected是VoidCallback回撥,用來進行路由的切換:
void _onDiscoveryComplete() { _navigatorKey.currentState!.pushNamed(routeFriendSelectPage); } void _onFriendSelected(String deviceId) { _navigatorKey.currentState!.pushNamed(routeFriendConnectingPage); } void _onConnectionEstablished() { _navigatorKey.currentState!.pushNamed(routeFriendFinishedPage); }
可以看到上面的路由切換實際上是在子路由上切換,跟父路由無關。
如果想要直接從子路由跳出到父路由該怎麼處理呢?很簡單,呼叫Navigator.of的pop方法即可:
void _exitSetup() { Navigator.of(context).pop(); }
這裡的context預設是全域性的context,所以會導致主路由的跳轉變化。
以上的程式碼執行結果如下:
雖然上面的例子看起來複雜,但是大家只要記住了不同的路由使用不同的Navigator範圍進行跳轉就行了。
到此這篇關於Flutter學習之建立一個內嵌的navigation詳解的文章就介紹到這了,更多相關Flutter建立內嵌navigation內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45