flutter 返回指定界面_Flutter页面路由导航及传参
轉(zhuǎn)載請注明出處: https://learnandfish.com/
概述
每個(gè)應(yīng)用都有很多個(gè)頁面,在flutter中同樣也有很多頁面,被稱之為路由(Router),頁面之間的跳轉(zhuǎn)通過導(dǎo)航器(Navigator)進(jìn)行管理。
其中 Navigator.push 和 Navigator.pop 是最簡單的跳轉(zhuǎn)到新頁面和返回到上一級界面的方式。
路由分為靜態(tài)路由(即命名路由)和動(dòng)態(tài)路由。頁面之間跳轉(zhuǎn)時(shí)往往需要傳遞參數(shù),這稱之為路由傳值。下面我們會一一帶領(lǐng)大家學(xué)習(xí)。
通過本篇文章的學(xué)習(xí)我們的目標(biāo)是熟練掌握路由及傳值,以后進(jìn)行應(yīng)用開發(fā)時(shí)對頁面跳轉(zhuǎn)方面不再疑惑。
靜態(tài)路由(即命名路由)
flutter中萬物皆widget,我們的頁面(route)也是widget的子類,所以我們定義一個(gè)界面也是通過繼承widget實(shí)現(xiàn)。
前面的博客我們已經(jīng)定義過界面了,比如計(jì)數(shù)器實(shí)例,就是一個(gè)簡單的頁面,也就是一個(gè)路由。下面我們來詳細(xì)實(shí)現(xiàn)一個(gè)界面。
首先我需要一個(gè)入口函數(shù),這個(gè)相信大家已經(jīng)很熟悉了,就是在main方法中調(diào)用runApp函數(shù)進(jìn)入應(yīng)用,我們就不做詳細(xì)介紹了,直接給出代碼。
上面的代碼是我們最常規(guī)的包含一個(gè)主頁面的應(yīng)用。后續(xù)我們寫應(yīng)用時(shí)候的基本框架也是在此基礎(chǔ)上進(jìn)行擴(kuò)展。
現(xiàn)在我們的想法是點(diǎn)擊這個(gè)頁面上的按鈕跳轉(zhuǎn)的第二個(gè)界面,首先我們需要構(gòu)造第二個(gè)界面。構(gòu)造第二個(gè)界面其實(shí)和我們構(gòu)造第一個(gè)
界面HomePage一樣,繼承widget重寫自己想要的樣式即可。實(shí)現(xiàn)了頁面就要開始跳轉(zhuǎn)邏輯。
靜態(tài)路由即命名路由,在通過Navigator進(jìn)行跳轉(zhuǎn)之前,需要在MaterialApp組件內(nèi)顯式聲明路由的名稱,一旦聲明,路由的跳轉(zhuǎn)
方式就固定了,所以稱之為靜態(tài)路由,有唯一的名稱所以也稱之為命令路由。顯式聲明路由通過在MaterialApp內(nèi)的routes屬性進(jìn)行定義。
如果我們有很多個(gè)頁面和很多個(gè)其他類型的組件都放在lib下,對于后期維護(hù)簡直是一大折磨,所以分包是大多數(shù)平臺的常規(guī)操作,
就是對有同一種特性的東西放置在同一個(gè)包下,比如頁面類的組件都放在pages包,工具類的組件放在utils包下等。
接下來我們就新建一個(gè)pages包,把第二個(gè)界面SecondPage放進(jìn)去,把第一個(gè)界面HomePage也提取出來放到這個(gè)包下。
我們分為一下三步進(jìn)行靜態(tài)路由的跳轉(zhuǎn):
- 首先在lib目錄右鍵新建pages包,接著在pages包下新建SecondPage.dart文件,然后把HomePage提取到pages下,成為單獨(dú)的類。
- 在RouteDemo類中的MaterialApp內(nèi)聲明routes屬性,為了顯示聲明路由的名稱。
- 使用Navigator進(jìn)行頁面的跳轉(zhuǎn)和返回。
首頁面單獨(dú)提取出來之后的代碼如下。
import 'package:flutter/material.dart';class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 通過Scaffold可以方便的生成一個(gè)Material風(fēng)格的頁面return Scaffold(// 頂部導(dǎo)航欄appBar: AppBar(title: Text("主頁面"),),body: Center(child: RaisedButton(child: Text("我是第一個(gè)界面,點(diǎn)擊我進(jìn)入第二個(gè)界面"),onPressed: () {print("我是第一個(gè)界面,點(diǎn)擊我進(jìn)入第二個(gè)界面");// 跳轉(zhuǎn)到第二個(gè)界面Navigator.pushNamed(context, '/secondPage');},),),);} }第二個(gè)頁面提取之后的代碼。
import 'package:flutter/material.dart';class SecondPage extends StatelessWidget {@overrideWidget build(BuildContext context) {// 通過Scaffold可以方便的生成一個(gè)Material風(fēng)格的頁面return Scaffold(// 頂部導(dǎo)航欄appBar: AppBar(title: Text("第二個(gè)界面"),),body: Center(child: RaisedButton(child: Text("我是第二個(gè)界面,點(diǎn)擊我進(jìn)入第二個(gè)界面"),onPressed: () {print("我是第二個(gè)界面,點(diǎn)擊我返回到第一個(gè)界面");// 返回上一個(gè)界面Navigator.pop(context);},),),);} }對于命名路由的跳轉(zhuǎn),通過Navigator.pushNamed方法調(diào)用,通過Navigator.pop方法返回上一級界面。
動(dòng)態(tài)路由
動(dòng)態(tài)路由不需要顯示聲明,直接通過代碼實(shí)現(xiàn)。
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// 常用固定寫法,生成Material風(fēng)格的Appreturn MaterialApp(title: "路由使用",theme: ThemeData(// 默認(rèn)為亮色主題,可以設(shè)置[Brightness.dark]變成黑暗模式brightness: Brightness.light,),home: HomePage(),);} }在HomePage界面通過調(diào)用Navigator.push方法實(shí)現(xiàn)跳轉(zhuǎn)。第二個(gè)頁面的返回邏輯不變。
Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage(),));動(dòng)態(tài)路由的相互傳參
有時(shí)候我們不僅需要跳轉(zhuǎn)到對應(yīng)界面,還需要傳遞一些參數(shù)給下一個(gè)界面,同時(shí)下一個(gè)界面返回時(shí),把某些參數(shù)再次傳遞給該界面。
我們修改SecondPage組件的構(gòu)造方法,為了接收需要傳遞的參數(shù)。這時(shí)候我們第二個(gè)頁面結(jié)構(gòu)如下:
第一個(gè)界面跳轉(zhuǎn)的地方代碼是這樣的。
Navigator.push(context,MaterialPageRoute(// 傳遞title為SecondPage,跳轉(zhuǎn)到第二個(gè)界面就會把標(biāo)題設(shè)置為SecondPagebuilder: (context) => SecondPage(title: "SecondPage"),));},說完了從第一個(gè)頁面往第二個(gè)頁面?zhèn)鬟f了參數(shù),如果第二個(gè)頁面返回時(shí)傳遞一句話,然后第一個(gè)頁面接收到這句話然后打印出來,
代碼修改如下:
靜態(tài)路由(即命名路由)的相互傳參
講完了動(dòng)態(tài)路由及動(dòng)態(tài)路由傳參之后,我們來講一下靜態(tài)路由傳參,參數(shù)的傳遞方式是flutter為我們定義好的,我們只需要把固定
代碼拷貝回來,稍微修改即可。為了更具有普遍性,我們再定義一個(gè)頁面ThirdPage。
在我們顯示聲明了routes之后,還需要在MaterialApp組件內(nèi)添加onGenerateRoute屬性內(nèi)容進(jìn)行參數(shù)傳遞的處理。
完整代碼如下:
第二個(gè)頁面?zhèn)鬟f參數(shù)時(shí)使用Navigator.pushNamed方法,具體代碼如下:
import 'package:flutter/material.dart';class SecondPage extends StatelessWidget {// 定義一個(gè)需要變量, 接收傳遞的參數(shù)final String title;// 為title設(shè)置一個(gè)默認(rèn)參數(shù),這樣的跳轉(zhuǎn)該界面時(shí)可以不傳值。SecondPage({Key key, this.title = "第二個(gè)界面"});@overrideWidget build(BuildContext context) {// 通過Scaffold可以方便的生成一個(gè)Material風(fēng)格的頁面return Scaffold(// 頂部導(dǎo)航欄appBar: AppBar(title: Text(title),),body: Center(child: RaisedButton(child: Text("我是第二個(gè)界面,點(diǎn)擊我進(jìn)入第二個(gè)界面"),onPressed: () {print("我是第二個(gè)界面,點(diǎn)擊我進(jìn)入第三個(gè)界面");// 通過arguments指定參數(shù)Navigator.pushNamed(context, "/thirdPage",arguments: {'title': "命令路由傳遞過來的title"});},),),);} }第三個(gè)頁面獲取參數(shù),完整代碼如下:
import 'package:flutter/material.dart';class ThirdPage extends StatelessWidget {final Map arguments;// 為title設(shè)置一個(gè)默認(rèn)參數(shù),這樣的跳轉(zhuǎn)該界面時(shí)可以不傳值。ThirdPage({Key key, this.arguments});@overrideWidget build(BuildContext context) {// 通過Scaffold可以方便的生成一個(gè)Material風(fēng)格的頁面return Scaffold(// 頂部導(dǎo)航欄appBar: AppBar(title: Text("${arguments != null ? arguments['title'] : "ThirdPage"}"),),body: Center(child: RaisedButton(child: Text("我是第三個(gè)界面,點(diǎn)擊我進(jìn)入第二個(gè)界面"),onPressed: () {print("我是第三個(gè)界面,點(diǎn)擊我返回到第二個(gè)界面");// 返回上一個(gè)界面Navigator.pop(context, "返回傳遞數(shù)據(jù)Page3");},),),);} }命名路由傳參優(yōu)化
上面我們已經(jīng)實(shí)現(xiàn)了參數(shù)的傳遞,但是routes頁面列表和onGenerateRoute比較固定,我們能夠把這兩個(gè)單獨(dú)提取出來成為
一個(gè)單獨(dú)的類,這樣后期再創(chuàng)建頁面或者維護(hù)的時(shí)候只需要修改這一個(gè)類就行了。
我們新建一個(gè)PageConstants類,進(jìn)行提取,修改后的代碼如下:
import 'package:flutter/material.dart';// 引入頁面路徑 import '../pages/HomePage.dart'; import '../pages/SecondPage.dart'; import '../pages/ThirdPage.dart';// 聲明所有頁面 final routes = {'/': (context, {arguments}) => HomePage(),'/secondPage': (context, {arguments}) => SecondPage(),'/thirdPage': (context, {arguments}) => ThirdPage(arguments: arguments), };// 處理參數(shù)傳遞 // ignore: top_level_function_literal_block var onGenerateRoute = (RouteSettings settings) {// 獲取聲明的路由頁面函數(shù)var pageBuilder = routes[settings.name];if (pageBuilder != null) {if (settings.arguments != null) {// 創(chuàng)建路由頁面并攜帶參數(shù)return MaterialPageRoute(builder: (context) =>pageBuilder(context, arguments: settings.arguments));} else {return MaterialPageRoute(builder: (context) => pageBuilder(context));}}return MaterialPageRoute(builder: (context) => HomePage()); };這時(shí)候我們只需要簡單修改MyApp組件即可:
import 'package:flutter/material.dart'; import 'package:hello_flutter/pages/PageConstants.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// 常用固定寫法,生成Material風(fēng)格的Appreturn MaterialApp(title: "路由使用",theme: ThemeData(// 默認(rèn)為亮色主題,可以設(shè)置[Brightness.dark]變成黑暗模式brightness: Brightness.light,),initialRoute: '/', // 默認(rèn)界面// 通過PageConstants引入onGenerateRoute: onGenerateRoute,);} }這樣來看就會清爽很多。
篇幅所限,這次的內(nèi)容就先講到這里,下篇文章繼續(xù)講往后的內(nèi)容,應(yīng)該會單獨(dú)講一講實(shí)現(xiàn)仿閑魚底部tab頁面切換和仿頭條多tab頁切換。
為了第一時(shí)間獲取最新文章,請關(guān)注公眾號 -- 程序員指北,每一個(gè)關(guān)注都能讓作者多搬一塊磚。
總結(jié)
以上是生活随笔為你收集整理的flutter 返回指定界面_Flutter页面路由导航及传参的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地球什么时候会毁灭(大约50亿年后地球毁
- 下一篇: 电脑硬盘gpt保护分区(磁盘管理 gpt