頂部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( 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,DefaultTabController的length屬性用於配置頂部TabBar的item數量,須要與TabBar的tabs的元素數量,以及TabBarView的children的元素數量保持一致。
2,TabBar的tabs中的Tab元素,以及TabBarView的children中的頁面元素是一一對應的,對應好了以後就能夠在頁面中對應展現了。
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;
void initState() { super.initState(); //第4步,初始化TabController實例 _tabController = TabController( vsync: this, length: 2,//這裏指定TabBar中的item數量 ); //第5步,監聽TabBar的各類頁面切換 _tabController.addListener((){ print(_tabController.index); }); } 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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。