Flutter中的AppBar、TabBar和TabController——頂部切換欄是如何實現的

頂部TabBar切換欄實現的第一種方式javascript


在Flutter中,AppBar用於定義頂部的導航欄:
java

Scaffold( appBar: AppBar( title: Text("AppBarPageDemo"), ), body: Center( child: Text("AppBarDemoPageContent"), ), );

效果以下:
typescript


實際上,AppBar 這個組件有許多的屬性,咱們經過這些屬性,能夠用來定義頂部導航欄的各類樣式。下面我將爲你一一說明這些屬性的做用:bash


  • title,導航欄的標題,是一個Widget,一般顯示爲當前界面的標題文字,可是也能夠放其餘的組件,好比能夠放TabBar。微信

  • backgroundColor,導航欄的背景顏色。網絡

  • leading,在導航欄最左側(標題前面)顯示的組件,在首頁一般顯示應用的logo,在其餘頁面一般顯示爲返回按鈕app

  • actions,在導航欄右側(標題後面)顯示的組件組,一般使用IconButton來表示,能夠放按鈕組。ide

  • centerTitle,標題是否居中顯示(不管是iOS仍是Android)flex

  • isScrollable,頂部TabBar是否能夠滾動。
    ui


以上幾個屬性是AppBar的經常使用屬性,其使用代碼以下:

Scaffold( appBar: AppBar( title: Text("AppBarPageDemo"), //標題 backgroundColor: Colors.pinkAccent, //背景顏色 //在導航欄標題左側添加的一個組件 leading: IconButton( onPressed: () => print("menu"), icon: Icon(Icons.menu), ), //在導航欄標題右側添加的組件組 actions: <Widget>[ IconButton( onPressed: () => print("settings"), icon: Icon(Icons.settings), ), IconButton( onPressed: () => print("edit"), icon: Icon(Icons.edit), ), IconButton( onPressed: () => print("photo"), icon: Icon(Icons.photo), ), ], centerTitle: true,//標題是否居中展現 ), body: Center( child: Text("AppBarDemoPageContent"), ), );


上述代碼的展現效果以下:


接下來咱們來聊聊AppBar的bottom屬性


通常而言,一個應用程序的首頁底部是有一個TabBar的,用於切換各個功能頁面,以下所示:


可是在有些狀況下,咱們須要在頂部也須要定義一個TabBar,用於切換不一樣的功能頁面,以下面這種頁面:


這個時候就須要用到AppBar的bottom屬性了。也就是說,咱們能夠將AppBar的bottom屬性值配置爲一個TabBar組件,以實如今頂部添加TabBar的效果


可是,要想給AppBar的bottom配置TabBar,那麼須要在Scaffold組件的外部再包一層DefaultTabController,代碼以下:

DefaultTabController(      length: 2,//第1步,這裏配置頂部tabbar的item個數 child: Scaffold( appBar: AppBar( //第2步,這裏配置頂部tabbar bottom: TabBar( tabs: <Widget>[Tab(text: "熱門"), Tab(text: "推薦")], ), title: Text("AppBarPageDemo"),  backgroundColor: Colors.pinkAccent,  ),        //第3步,這裏配置頂部TabBar每個item所對應的頁面,其元素數量須要與TabBar的item數量保持一致 body: TabBarView( children: <Widget>[ Text("熱門頁面"), Text("推薦頁面") ], ), ), );


運行結果以下:


對於上面代碼,須要如下幾點:

1,DefaultTabControllerlength屬性用於配置頂部TabBar的item數量,須要與TabBartabs的元素數量,以及TabBarViewchildren的元素數量保持一致。

2,TabBartabs中的Tab元素,以及TabBarViewchildren中的頁面元素是一一對應的,對應好了以後就能夠在頁面中對應展現了

3,在默認狀況下,導航欄右上角有一個debug字樣,以下:

若是我想把這個DEBUG字樣去掉,那麼能夠在MaterialApp中配置debugShowCheckedModeBanner屬性爲false

MaterialApp( // home: Tabs(), initialRoute: "/",//初始化的時候加載的路由 //統一處理命名路由 onGenerateRoute: prefix0.onGenerateRoute, //去掉導航欄默認的debug圖標 debugShowCheckedModeBanner: false, );

再運行,咱們發現DEBUG字樣消失了:



咱們上面講的都是頁面中只有一個AppBar的狀況,這個時候若是想要加一個頂部TabBar,那麼只須要配置APPBar的bottom屬性便可。可是有些時候,咱們會遇到不可自定義原始的AppBar的場景,而咱們又想實現頂部TabBar的效果,此時咱們就能夠在頁面中再加一個Scaffold組件,而後這樣就有兩個AppBar了。咱們能夠經過配置第二個AppBar來實現頂部TabBar的效果。


其實此時也是考驗咱們對AppBar以及TabBar的瞭解程度了。


AppBar是一個頂部導航欄,它的title屬性用於配置標題,title對應的是一個組件,咱們通常給title賦值爲一個Text組件,可是也可根據需求給title賦值其餘的組件。

AppBar的bottom屬性,其對應的也是一個組件,咱們通常給bottom屬性賦值爲TabBar組件,以實現頂部TabBar的效果

若是在一個頁面中,一個Scaffold組件內部還嵌套了另一個Scaffold組件,而且兩個Scaffold組件都配置了appbar,那麼就會是以下的展現效果:

以上是兩個Scaffold的appBar都配置了title,但沒有配置bottom。


好,咱們如今來考慮一下,在有兩個Scaffold的場景下,如何實現頂部TabBar的效果。咱們能夠像上面所講的,給內層的Scaffold組件的appBar配置bottom屬性值爲TabBar組件,可是這樣的話,內層的Scaffold組件的title的位置就會有一個留空,很差看,以下所示:


爲了使頁面更好看,咱們能夠將這個頂層的TabBar賦值給內層Scaffold的appBar的title屬性,前面也說了,title對應的也是一個組件。這樣就能完美解決留空的問題了。代碼以下:

DefaultTabController( length: 3,//頂部tabbar的元素數量 child: Scaffold( appBar: AppBar( //配置頂部tabbar title: TabBar( tabs: <Widget>[Tab(text: "熱銷"), Tab(text: "推薦"), Tab(text: "打折")], ), ),        //這裏配置頂部Tabbar所對應的頁面 body: TabBarView( children: <Widget>[ Stack(              ... ), Text("222"), Text("333") ], ), ), );


效果以下:


須要注意的一點是,若是咱們想要經過配置AppBar的title或者bottom來實現頂部TabBar的效果,必定要在Scaffold組件外面再包一層DefaultTabController組件


好,如今咱們已經知道該如何利用AppBar和TabBar來實現頂部Tabbar的視覺效果了。在本文的最後,咱們來了解一下如何個性化設置頂部TabBar導航條。


TabBar的經常使用屬性以下:

  • tabs,顯示的標籤內容,通常使用Tab對象,也能夠是其餘的Widget

  • isScrollable,是否可滾動

  • indicatorColor,底部指示條的顏色

  • indicatorWeight,底部指示條的高度

  • indicatorSize,指示器大小計算方式,TabBarIndicatorSize.label 跟文 字等寬,TabBarIndicatorSize.tab 跟每一個 tab 等寬

  • labelColor,選中的文字顏色

  • unselectedLabelColor,未選中的文字顏色


示例代碼以下:

DefaultTabController( length: 6,//這裏配置頂部tabbar的item個數 child: Scaffold( appBar: AppBar( //這裏配置頂部tabbar bottom: TabBar( indicatorColor: Colors.yellow, indicatorWeight: 10, indicatorSize: TabBarIndicatorSize.label, labelColor: Colors.orange, unselectedLabelColor: Colors.white, tabs: <Widget>[Tab(text: "熱門"), Tab(text: "推薦"), Tab(text: "熱門"), Tab(text: "推薦"), Tab(text: "熱門"), Tab(text: "推薦")], ), title: Text("AppBarPageDemo"),  backgroundColor: Colors.pinkAccent,  ), //這裏配置頂部TabBar每個item所對應的頁面,其元素數量須要與TabBar的item數量保持一致 body: TabBarView( children: <Widget>[ Text("熱門頁面"), Text("推薦頁面"), Text("熱門頁面"), Text("推薦頁面"), Text("熱門頁面"), Text("推薦頁面") ], ), ), );


展現效果以下:


頂部TabBar切換欄實現的第二種方式


上面咱們已經實現了頂部TabBar切換欄的UI效果,可是上面這種方式咱們很差監聽頁面切換,當頁面中有網絡請求、上拉刷新下拉加載等需求的時候,咱們利用第一種方式就不容易實現。所幸咱們還有第二種方式,那就是利用

TabController 來實現頂部Tab切換。


步驟以下:

1,頁面(TabBarControllerPage)必須是繼承自StatefulWidget,也就是說,頁面必須是動態頁面。

2,頁面的state(_TabBarControllerPageState)要實現SingleTickerProviderStateMixin類。

3,在頁面的state(_TabBarControllerPageState)中要聲明並初始化一個TabController實例 (_tabController

4,在 TabBar 和 TabBarView 中都配置一下 controller 屬性

5,經過_tabController.addListener監聽各類事件,以處理業務邏輯。



import 'package:flutter/material.dart';
//第1步,頁面必須是動態頁面class TabBarControllerPage extends StatefulWidget { TabBarControllerPage({Key key}) : super(key: key);
_TabBarControllerPageState createState() => _TabBarControllerPageState();}
//第2步,經過mixins「繼承」自SingleTickerProviderStateMixin類class _TabBarControllerPageState extends State<TabBarControllerPage> with SingleTickerProviderStateMixin {   //第3步,聲明TabController實例 TabController _tabController;
@override void initState() { super.initState();    //第4步,初始化TabController實例 _tabController = TabController( vsync: this, length: 2,//這裏指定TabBar中的item數量 ); //第5步,監聽TabBar的各類頁面切換 _tabController.addListener((){ print(_tabController.index); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("TabBarControllerPage"), bottom: TabBar( //第6步,配置TabBar的controller controller: _tabController, tabs: <Widget>[Tab(text: "熱門"), Tab(text: "推薦")], ), ), body: TabBarView(        //第7步,配置TabBarView的controller controller: _tabController, children: <Widget>[Text("熱門"), Text("推薦")], ), ); }}


效果以下:


第二種方式的好處是,咱們能夠在_tabController.addListener監聽一些Tab切換的事件,以下所示:

 _tabController.addListener((){ print(_tabController.index); });


以上。


本文分享自微信公衆號 - iOS小生活(iOSHappyLife)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索