欧美大屁股bbbbxxxx,狼人大香伊蕉国产www亚洲,男ji大巴进入女人的视频小说,男人把ji大巴放进女人免费视频,免费情侣作爱视频

歡迎來(lái)到入門教程網(wǎng)!

Android

當(dāng)前位置:主頁(yè) > 軟件編程 > Android >

Flutter開(kāi)發(fā)之路由與導(dǎo)航的實(shí)現(xiàn)

來(lái)源:本站原創(chuàng)|時(shí)間:2020-01-10|欄目:Android|點(diǎn)擊: 次

如果說(shuō)構(gòu)成視圖元素的基本單位是組件,那么構(gòu)成應(yīng)用程序的基本單位就是頁(yè)面。對(duì)于擁有多個(gè)頁(yè)面的應(yīng)用程序而言,如何從一個(gè)頁(yè)面平滑地過(guò)渡到另一個(gè)頁(yè)面,是技術(shù)框架需要考慮的問(wèn)題。

在前端開(kāi)發(fā)中,可以使用路由框架來(lái)統(tǒng)一管理頁(yè)面及它們之間的跳轉(zhuǎn)。在Android中路由指的是一個(gè)Activity,在iOS中指的是一個(gè)ViewController,可以通過(guò)startActivity或pushViewController來(lái)打開(kāi)一個(gè)新的路由。在Flutter中,路由的管理和導(dǎo)航借鑒了前端和客戶端的設(shè)計(jì)思路,需要使用Route和Navigator來(lái)進(jìn)行統(tǒng)一管理。

其中,Route是頁(yè)面的抽象,主要負(fù)責(zé)創(chuàng)建界面、接收參數(shù)以及響應(yīng)導(dǎo)航器Navigator的打開(kāi)與關(guān)閉。而Navigator則用于維護(hù)路由棧管理,Route打開(kāi)即入棧,Route關(guān)閉即出棧,當(dāng)然還可以替換棧內(nèi)的某一個(gè)Route。作為官方提供的路由管理組件,Navigator提供了一系列方法來(lái)管理路由棧,其中最常用的兩個(gè)方法是push()和pop(),它們的含義如下。

  • push():將給定的路由入棧,返回值是一個(gè)Future對(duì)象,用以接收路由出棧時(shí)的返回?cái)?shù)據(jù)。
  • pop():將棧頂路由出棧,返回結(jié)果為頁(yè)面關(guān)閉時(shí)返回給上一個(gè)頁(yè)面的數(shù)據(jù)。

除了push()和pop()方法外,Navigator還提供了很多其它實(shí)用的方法,如replace()、removeRoute()和popUntil()等,可以根據(jù)使用場(chǎng)景合理的選取。

根據(jù)是否需要提前注冊(cè)頁(yè)面標(biāo)識(shí)符,F(xiàn)lutter中的路由管理可以分為基本路由和命名路由兩種。

  • 基本路由:無(wú)需提前注冊(cè),在頁(yè)面切換時(shí)需要手動(dòng)構(gòu)造頁(yè)面的實(shí)例。
  • 命名路由:需要提前注冊(cè)頁(yè)面標(biāo)識(shí)符,在頁(yè)面切換時(shí)通過(guò)標(biāo)識(shí)符直接打開(kāi)新的路由。

下面就讓我們重點(diǎn)來(lái)看一下Flutter中的路由管理的基本路由和命名路由等相關(guān)知識(shí)。

基本路由

在Flutter開(kāi)發(fā)中,基本路由的使用方式和原生Android、iOS打開(kāi)新頁(yè)面的方式非常類似。要打開(kāi)一個(gè)新的頁(yè)面,只需要?jiǎng)?chuàng)建一個(gè)MaterialPageRoute對(duì)象實(shí)例,然后調(diào)用Navigator.push()方法將新頁(yè)面壓到路由堆棧的頂部即可,如果要返回上一個(gè)頁(yè)面,則可以調(diào)用Navigator.pop()方法。

其中,MaterialPageRoute是一種路由模板,定義了路由創(chuàng)建以及路由切換過(guò)渡動(dòng)畫(huà)的相關(guān)配置,該配置可以根據(jù)不同的平臺(tái)實(shí)現(xiàn)與平臺(tái)頁(yè)面切換動(dòng)畫(huà)風(fēng)格一致的路由切換動(dòng)畫(huà)。下面是使用Navigator實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的示例,代碼如下。

class FirstPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text('第一個(gè)頁(yè)面'),
  ),
  body: Center(
  child: RaisedButton(
   child: Text('跳轉(zhuǎn)到第二個(gè)頁(yè)面'),
   onPressed: () => Navigator.push(context,
    MaterialPageRoute(builder: (context) => SecondPage()))),
  ),
 );
 }
}

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text('第二個(gè)頁(yè)面'),
  ),
  body: Center(
  child: RaisedButton(
   child: Text('返回上一個(gè)頁(yè)面'),
 onPressed: () => Navigator.pop(context)),
  ),
 );
 }
}

在上面的示例中,我們創(chuàng)建了兩個(gè)頁(yè)面,每個(gè)頁(yè)面都包含一個(gè)按鈕。當(dāng)點(diǎn)擊第一個(gè)頁(yè)面上的按鈕時(shí)將導(dǎo)航到第二個(gè)頁(yè)面,點(diǎn)擊第二個(gè)頁(yè)面上的按鈕將返回第一個(gè)頁(yè)面。運(yùn)行上面的代碼,效果如下圖所示。

可以發(fā)現(xiàn),跳轉(zhuǎn)頁(yè)面使用的是Navigator.push()方法,該方法可以將一個(gè)新的路由添加到由Navigator管理的路由對(duì)象的棧頂。而創(chuàng)建新的路由對(duì)象使用的是MaterialPageRoute,MaterialPageRoute是PageRoute的子類,定義了路由創(chuàng)建及切換時(shí)過(guò)渡動(dòng)畫(huà)的相關(guān)接口及屬性,并且自帶頁(yè)面切換動(dòng)畫(huà),Android平臺(tái)頁(yè)面進(jìn)入動(dòng)畫(huà)是向上滑動(dòng)并淡出,退出是相反,iOS平臺(tái)頁(yè)面進(jìn)入動(dòng)畫(huà)是從右側(cè)滑入,退出則相反。

命名路由

基本路由的使用方式相對(duì)簡(jiǎn)單靈活,適用于應(yīng)用中頁(yè)面不多的場(chǎng)景。而對(duì)于應(yīng)用中頁(yè)面比較多的情況下,如果再使用基本路由方式,那么每次跳轉(zhuǎn)一個(gè)新的頁(yè)面都要手動(dòng)創(chuàng)建MaterialPageRoute實(shí)例,然后再調(diào)用push()方法來(lái)打開(kāi)一個(gè)新的頁(yè)面,此時(shí)頁(yè)面的管理和跳轉(zhuǎn)就比較混亂。

為了避免頻繁的創(chuàng)建MaterialPageRoute實(shí)例,F(xiàn)lutter提供了另外一種方式來(lái)簡(jiǎn)化路由管理,即命名路由。所謂命名路由,就是給頁(yè)面起一個(gè)別名,然后使用頁(yè)面的別名就可以打開(kāi)它,使用此種方式來(lái)管理路由,使得路由的管理更加清晰直觀。

要想通過(guò)別名來(lái)指定頁(yè)面切換,必須先給應(yīng)用程序MaterialApp提供一個(gè)頁(yè)面名稱映射規(guī)則,即路由表。路由表是一個(gè)Map<String,WidgetBuilder>的結(jié)構(gòu),其中key對(duì)應(yīng)頁(yè)面名字,value則是對(duì)應(yīng)的頁(yè)面,如下所示。

MaterialApp(
 ...   //其他配置
 routes:{      //注冊(cè)路由
  'first':(context)=>FirstPage(),
  'second':(context)=>SecondPage(),
},
initialRoute: 'first',   //初始路由頁(yè)面
);

在路由表中注冊(cè)好頁(yè)面后,然后就可以通過(guò)Navigator.pushNamed()方法來(lái)打開(kāi)頁(yè)面,如下所示。

Navigator.pushNamed(context,"second "); // second表示頁(yè)面別名

不過(guò),由于路由的注冊(cè)和使用都采用字符串來(lái)標(biāo)識(shí),這就會(huì)帶來(lái)一個(gè)問(wèn)題,即如果打開(kāi)一個(gè)不存在的路由頁(yè)面。對(duì)應(yīng)這類問(wèn)題,移動(dòng)應(yīng)用有一個(gè)通用的解決方案,即跳轉(zhuǎn)到一個(gè)統(tǒng)一的錯(cuò)誤頁(yè)面。在注冊(cè)路由表時(shí),F(xiàn)lutter提供了一個(gè)UnknownRoute屬性,用來(lái)對(duì)未知的路由標(biāo)識(shí)符進(jìn)行統(tǒng)一的頁(yè)面跳轉(zhuǎn)處理,如下所示。

MaterialApp(
 …
routes:{},
 onUnknownRoute: (RouteSettings setting) => MaterialPageRoute(builder: (context) => UnknownPage()),  //錯(cuò)誤路由處理,返回UnknownPage
);

class UnknownPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text('錯(cuò)誤路由'),
  ),
 );
 }
}

路由嵌套

有時(shí)候,一個(gè)應(yīng)用可能不止一個(gè)導(dǎo)航器,而是可能有多個(gè)導(dǎo)航器,將一個(gè)導(dǎo)航器嵌套在另一個(gè)導(dǎo)航器的行為稱為路由嵌套。路由嵌套在移動(dòng)開(kāi)發(fā)中是很常見(jiàn)的,比如,移動(dòng)開(kāi)發(fā)中經(jīng)常會(huì)看到應(yīng)用主頁(yè)有底部導(dǎo)航欄,每個(gè)底部導(dǎo)航欄又嵌套其他頁(yè)面的情況,效果如下圖所示。

要實(shí)現(xiàn)上面的示例效果,首先需要新建一個(gè)底部導(dǎo)航欄,然后再由底部導(dǎo)航欄去嵌套其他子路由。關(guān)于底部導(dǎo)航欄的實(shí)現(xiàn),可以直接使用Scaffold布局組件的bottomNavigationBar屬性實(shí)現(xiàn),如下所示。

class MainPage extends StatefulWidget {
 @override
 State<StatefulWidget> createState() {
 return MainPageState();
 }
}

class MainPageState extends State<MainPage> {
 int currentIndex = 0;  //底部導(dǎo)航欄索引
 final List<Widget> children = [
 HomePage(),   //首頁(yè)
 MinePage(),   //我的
 ];

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  body: children[currentIndex],
  bottomNavigationBar: BottomNavigationBar(
  onTap: onTabTapped,
  currentIndex: currentIndex,
  items: [
   BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首頁(yè)')),
   BottomNavigationBarItem(icon: Icon(Icons.person), title: Text('我的')),
  ],
  ),
 );
 }

 void onTabTapped(int index) {
 setState(() {
  currentIndex = index;
 });
 }
}

然后,每個(gè)底部導(dǎo)航欄會(huì)嵌套一個(gè)子路由,然后子路由再去管理對(duì)應(yīng)的路由頁(yè)面。在Flutter中,創(chuàng)建子路由需要使用Navigator組件,并且子路由的攔截需要使用onGenerateRoute屬性,如下所示。

class HomePage extends StatelessWidget {

 @override
 Widget build(BuildContext context) {
 return Navigator(
  initialRoute: 'first',
  onGenerateRoute: (RouteSettings settings) {
  WidgetBuilder builder;
  switch (settings.name) {
   case 'first':
   builder = (BuildContext context) => FirstPage();
   break;
   case 'second':
   builder = (BuildContext context) => SecondPage();
   break;
  }
  return new MaterialPageRoute(builder: builder, settings: settings);
  },
 );
 }
}

運(yùn)行上面的代碼,當(dāng)點(diǎn)擊子路由頁(yè)面上的按鈕時(shí),底部的導(dǎo)航欄欄并不會(huì)消失,這是因?yàn)樽勇酚蓛H在自己的范圍內(nèi)有效。要想跳轉(zhuǎn)到其他子路由管理的頁(yè)面,就需要在根導(dǎo)航器中進(jìn)行注冊(cè),也就是MaterialApp內(nèi)部的導(dǎo)航器。

路由傳參

在移動(dòng)應(yīng)用開(kāi)發(fā)中,頁(yè)面參數(shù)的傳遞也是一個(gè)比較常見(jiàn)的需求。為了滿足不同場(chǎng)景下頁(yè)面跳轉(zhuǎn)過(guò)程中參數(shù)傳遞的需求,F(xiàn)lutter提供了路由參數(shù)機(jī)制,可以在打開(kāi)路由時(shí)傳遞參數(shù),然后在目標(biāo)頁(yè)面通過(guò)RouteSettings來(lái)獲取頁(yè)面?zhèn)鬟f的參數(shù),如下所示。

Navigator.of(context).pushNamed("second ", arguments: " from first page");

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
//取出路由參數(shù)
 String msg = ModalRoute.of(context).settings.arguments as String; 
  … //數(shù)據(jù)處理
 }
}

除此之外,對(duì)于某些特定的頁(yè)面,還需要在其關(guān)閉時(shí)回傳頁(yè)面處理的處理結(jié)果。這與Android提供的startActivityForResult()方法監(jiān)聽(tīng)目標(biāo)頁(yè)面返回處理結(jié)果的場(chǎng)景類似,F(xiàn)lutter也提供了頁(yè)面返回的參數(shù)機(jī)制。具體來(lái)說(shuō),就是在使用push()方法打開(kāi)目標(biāo)頁(yè)面時(shí),可以設(shè)置目標(biāo)頁(yè)面關(guān)閉時(shí)監(jiān)聽(tīng)函數(shù)來(lái)獲取返回參數(shù),當(dāng)目標(biāo)頁(yè)面關(guān)閉路由時(shí)使用pop()方法回傳參數(shù)即可。例如,下面是兩個(gè)頁(yè)面之間參數(shù)值傳遞和參數(shù)值回傳,代碼如下。

class FirstPage extends StatefulWidget {
 @override
 State<StatefulWidget> createState() {
 return FirstPageState();
 }
}

class FirstPageState extends State<FirstPage> {
 
String result = '';

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  body: Center(
   child: Column(
  children: <Widget>[
   Text('from seconde page: ' + result, style: TextStyle(fontSize: 20)),
   RaisedButton(
    child: Text('跳轉(zhuǎn)'),
    //使用then()獲取目標(biāo)頁(yè)面返回參數(shù)
    onPressed: () => Navigator.of(context)
     .pushNamed("second", arguments: "from first page")
     .then((msg) => setState(() => result = msg)))
  ],
  )),
 );
 }
}

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {

 String msg = ModalRoute.of(context).settings.arguments as String;

 return Scaffold(
  body: Center(
   child: Column(children: [
   Text('from first screen: ' + msg, style: TextStyle(fontSize: 20)),
   RaisedButton(
    child: Text('返回'),
    onPressed: () => Navigator.pop(context, "from second page"))
   ]),
  ));
 }
}

運(yùn)行上面的代碼,可以看到,當(dāng)SecondPage頁(yè)面被關(guān)閉重新回到FirstPage頁(yè)面時(shí),F(xiàn)irstPage會(huì)把回傳的參數(shù)值展示出來(lái),最終效果如下圖所示。

MaterialPageRoute

在使用路由過(guò)程中,經(jīng)過(guò)會(huì)使用到MaterialPageRoute類。MaterialPageRoute繼承自PageRoute類,PageRoute類是一個(gè)抽象類,表示占有整個(gè)屏幕空間的一個(gè)模態(tài)路由頁(yè)面,它還定義了路由構(gòu)建及切換時(shí)過(guò)渡動(dòng)畫(huà)的相關(guān)接口及屬性。

MaterialPageRoute 是Material組件庫(kù)提供的組件,它可以針對(duì)不同平臺(tái),實(shí)現(xiàn)與平臺(tái)頁(yè)面切換動(dòng)畫(huà)風(fēng)格一致的路由切換動(dòng)畫(huà):當(dāng)打開(kāi)頁(yè)面時(shí),新的頁(yè)面會(huì)從屏幕右側(cè)邊緣一致滑動(dòng)到屏幕左邊,直到新頁(yè)面全部顯示到屏幕上,而上一個(gè)頁(yè)面則會(huì)從當(dāng)前屏幕滑動(dòng)到屏幕左側(cè)而消失;當(dāng)關(guān)閉頁(yè)面時(shí),正好相反,當(dāng)前頁(yè)面會(huì)從屏幕右側(cè)滑出,同時(shí)上一個(gè)頁(yè)面會(huì)從屏幕左側(cè)滑入。

MaterialPageRoute 構(gòu)造函數(shù)和各個(gè)參數(shù)的意義如下:

MaterialPageRoute({
 @required this.builder,
 RouteSettings settings,
 this.maintainState = true,
 bool fullscreenDialog = false,
 }) 

它們的具體含義如下:

  • builder :是一個(gè)WidgetBuilder類型的回調(diào)函數(shù),它的作用是構(gòu)建路由頁(yè)面的具體內(nèi)容,返回值是一個(gè)widget。我們通常要實(shí)現(xiàn)此回調(diào),返回新路由的實(shí)例。
  • settings: 包含路由的配置信息,如路由名稱、是否初始路由(首頁(yè))。
  • maintainState:默認(rèn)情況下,當(dāng)入棧一個(gè)新路由時(shí),原來(lái)的路由仍然會(huì)被保存在內(nèi)存中,如果想在路由沒(méi)用的時(shí)候釋放其所占用的所有資源,可以設(shè)置maintainState為false。
  • fullscreenDialog:表示新的路由頁(yè)面是否是一個(gè)全屏的模態(tài)對(duì)話框,在iOS中,如果fullscreenDialog為true,新頁(yè)面將會(huì)從屏幕底部滑入(而不是水平方向)。

總結(jié)

Flutter 提供了基本路由和命名路由兩種方式,來(lái)管理頁(yè)面間的跳轉(zhuǎn)。其中,基本路由需要自己手動(dòng)創(chuàng)建頁(yè)面實(shí)例,通過(guò) Navigator.push 完成頁(yè)面跳轉(zhuǎn);而命名路由需要提前注冊(cè)頁(yè)面標(biāo)識(shí)符和頁(yè)面創(chuàng)建方法,通過(guò) Navigator.pushNamed 傳入標(biāo)識(shí)符實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)。

對(duì)于命名路由,如果我們需要響應(yīng)錯(cuò)誤路由標(biāo)識(shí)符,還需要一并注冊(cè) UnknownRoute。為了精細(xì)化控制路由切換,F(xiàn)lutter 提供了頁(yè)面打開(kāi)與頁(yè)面關(guān)閉的參數(shù)機(jī)制,我們可以在頁(yè)面創(chuàng)建和目標(biāo)頁(yè)面關(guān)閉時(shí),取出相應(yīng)的參數(shù)??梢钥吹剑P(guān)于路由導(dǎo)航,F(xiàn)lutter 綜合了 Android、iOS 和 React 的特點(diǎn),簡(jiǎn)潔而不失強(qiáng)大。

在中大型應(yīng)用中,通常還會(huì)使用命名路由來(lái)管理頁(yè)面間的切換。命名路由的最重要作用,就是建立了字符串標(biāo)識(shí)符與各個(gè)頁(yè)面之間的映射關(guān)系,使得各個(gè)頁(yè)面之間完全解耦,應(yīng)用內(nèi)頁(yè)面的切換只需要通過(guò)一個(gè)字符串標(biāo)識(shí)符就可以搞定,為后期模塊化打好基礎(chǔ)。

除此之外,嵌套路由和路由傳參也是路由框架中比較核心的內(nèi)容。本篇只是Flutter路由與導(dǎo)航的基本知識(shí),后面將會(huì)從pushReplacementNamed 、 popAndPushNamed、pushNamedAndRemoveUntil和popUntil,以及第三方導(dǎo)航庫(kù)和源碼分析等方面來(lái)深入介紹Flutter的路由開(kāi)發(fā)與導(dǎo)航。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。

上一篇:使用AccessibilityService實(shí)現(xiàn)自動(dòng)遍歷點(diǎn)贊功能

欄    目:Android

下一篇:Android評(píng)分RationBar控件使用詳解

本文標(biāo)題:Flutter開(kāi)發(fā)之路由與導(dǎo)航的實(shí)現(xiàn)

本文地址:http://mengdiqiu.com.cn/a1/Android/9003.html

網(wǎng)頁(yè)制作CMS教程網(wǎng)絡(luò)編程軟件編程腳本語(yǔ)言數(shù)據(jù)庫(kù)服務(wù)器

如果侵犯了您的權(quán)利,請(qǐng)與我們聯(lián)系,我們將在24小時(shí)內(nèi)進(jìn)行處理、任何非本站因素導(dǎo)致的法律后果,本站均不負(fù)任何責(zé)任。

聯(lián)系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網(wǎng) 版權(quán)所有