Flutter 頂部導(dǎo)航欄實現(xiàn):TabBar + TabBarView + TabController


前言

Flutter 作為Google出品的一個新興的跨平臺移動客戶端UI開發(fā)框架约啊,正在被越來越多的開發(fā)者和組織使用,包括阿里的咸魚、騰訊的微信等拙徽。

示意圖

示意圖

今天,我主要講解Flutter中布局方面的頂部導(dǎo)航欄TabBar + TabBarView + TabController诗宣,希望你們會喜歡膘怕。

示意圖

目錄


1. 簡介

Flutter中用于快速實現(xiàn)頂部導(dǎo)航欄的組件庫(Widget)


示意圖

2. 作用

  • TabBar:導(dǎo)航欄標(biāo)題內(nèi)容
  • TabBarView:描述導(dǎo)航欄當(dāng)前所對應(yīng)的內(nèi)容區(qū)(容器)
  • TabController:關(guān)聯(lián)TabBar和TabBarView,即 哪個Tab對應(yīng)哪個內(nèi)容區(qū)
    示意圖

3. 具體介紹

參數(shù)說明如下:

/**
  *  TabBar
  **/
const TabBar({
    Key key,
    @required this.tabs,// 子標(biāo)簽梧田,一般使用Tab對象,當(dāng)然也可以是其他的Widget
    this.controller,// 控制器淳蔼,即TabController對象
    this.isScrollable = false,// 能否滑動。false:每個tab的寬度則等比裁眯,true:tab寬度則包裹item
    this.indicatorColor,// 指示器顏色
    this.indicatorWeight = 2.0, // 指示器厚度
    this.indicatorPadding = EdgeInsets.zero, // 底部指示器的Padding
    this.indicator, // 指示器decoration鹉梨,如邊框等
    this.indicatorSize,// 指示器大小計算方式 - TabBarIndicatorSize.label:indicator與文字同寬,TabBarIndicatorSize.tab:與tab同寬
    this.labelColor,// 選中標(biāo)簽顏色
    this.labelStyle,// 選中標(biāo)簽樣式
    this.labelPadding, // 選中標(biāo)簽的padding
    this.unselectedLabelColor,// 未選中標(biāo)簽顏色
    this.unselectedLabelStyle, // 未選中Tab中文字style
    this.dragStartBehavior = DragStartBehavior.down,
    this.onTap,// 點擊事件
  })

/**
  *  TabBarView
  **/
 const TabBarView({
    Key key,
    @required this.children,//子widget
    this.controller,//控制器
    this.physics,
    this.dragStartBehavior = DragStartBehavior.down,
  })

 /**
  *  TabController
  **/
TabController({ int initialIndex = 0, @required this.length, @required TickerProvider vsync })
    _index = initialIndex, // 當(dāng)前選中Tab的下標(biāo)穿稳。注:改變index也會更新 previousIndex存皂、設(shè)置animation's的value值、重置indexIsChanging為false并且通知監(jiān)聽器
    _previousIndex = initialIndex, // 上一個選中tab的index值逢艘,最初與index相同
    _animationController = AnimationController.unbounded( 
      value: initialIndex.toDouble(),
      vsync: vsync,
    ); // 該動畫值表示當(dāng)前TabBar選中的指示器位置以及TabBar和TabBarView的scrollOffsets

// 構(gòu)造函數(shù)的參數(shù):
// 參數(shù)1:初始顯示的tab位置
// 參數(shù)2:tab的個數(shù)
// 參數(shù)3:動畫效果的異步處理旦袋,默認(rèn)格式

// 特別注意:參數(shù)indexIsChanging(bool)
// true:當(dāng)動畫從上一個跳到下一個時

4. 使用說明

/**
*  TabController
*  作用:關(guān)聯(lián)TabBar和TabBarView,即 哪個Tab對應(yīng)哪個內(nèi)容區(qū)
**/
TabController mController = TabController(initialIndex: 0,length: 3, vsync: this);
// 初始化TabController
// 參數(shù)1:初始顯示的tab位置
// 參數(shù)2:tab的個數(shù)
// 參數(shù)3:動畫效果的異步處理它改,默認(rèn)格式

// 添加監(jiān)聽器
mController.addListener(() => _onTabChanged());

// 監(jiān)聽函數(shù)
_onTabChanged() {
print(mController.index);
}

/**
*  TabBar
*  導(dǎo)航欄標(biāo)題內(nèi)容
**/
// 1. 設(shè)置要顯示的list內(nèi)容(要與TabController的長度對應(yīng))
final List<Tab> titleTabs = <Tab>[
    Tab(
      text: 'Android',
    ),
    Tab(
      text: 'iOS',
    ),
    Tab(
      text: 'Web',
    ),
   ...
  ];

// 2. 創(chuàng)建TabBar組件 & 屬性
new TabBar(
  controller: mController,// 設(shè)置控制器
  labelColor: Colors.green, //選中的顏色
  labelStyle: TextStyle(fontSize: 16), //選中的樣式
  unselectedLabelColor: Colors.black, //未選中的顏色
  unselectedLabelStyle: TextStyle(fontSize: 14), //未選中的樣式
  indicatorColor: Colors.green, //下劃線顏色
  isScrollable: false, //是否可滑動疤孕,設(shè)置不可滑動,則是tab的寬度等長
  //tab標(biāo)簽
  tabs: titleTabs, // 設(shè)置標(biāo)題(上面設(shè)置的內(nèi)容)

  // 同樣是點擊事件(i是當(dāng)前點擊Tap的下標(biāo)數(shù))
  onTap: (int i) {
    print(i);
  },
),

/**
*  TabBarView
*  導(dǎo)航欄每個標(biāo)題對飲的內(nèi)容
**/
new TabBarView(
      controller: mController, // 設(shè)置控制器
      children:  <Widget>[ // 每個空間對應(yīng)的頁面央拖,此處根據(jù)需求進(jìn)行返回((要與TabController的長度對應(yīng)))
    Center(child:Text('Android')),
    Center(child:Text('iOS')),
    Center(child:Text('Web')),
    ...
    ],
    ),
  );

5. 實例說明

本次采用的實例 = 3個Tab

示意圖

具體代碼如下:

main.dart

// Flutter入口
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TabViewDemo(),// 自己設(shè)置的TabView類
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
    );
  }
}

TabViewDemo.dart

import 'package:flutter/material.dart'; // Material UI組件庫
import 'dart:ui';

class TabViewDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _TabViewState();
  }
}

class _TabViewState extends State<TabViewDemo> with SingleTickerProviderStateMixin {

  TabController mController;// tab控制器

  final List<Tab> titleTabs = <Tab>[
    Tab(
      text: 'Android',
    ),
    Tab(
      text: 'iOS',
    ),
    Tab(
      text: 'Web',
    ),

  ];

  @override
  void initState() {
    super.initState();

    mController = TabController(initialIndex: 0,length: 3, vsync: this);
    // 初始化TabController
    // 參數(shù)1:初試顯示的tab位置
    // 參數(shù)2:tab的個數(shù)
    // 參數(shù)3:動畫效果的異步處理祭阀,默認(rèn)格式

    // 添加監(jiān)聽器
    mController.addListener(() => _onTabChanged());

  }

  @override
  Widget build(BuildContext context) {
    return  new Scaffold(
        // 創(chuàng)建TabBar & 設(shè)置屬性
        appBar: new TabBar(
          controller: mController,// 設(shè)置控制器
          labelColor: Colors.green, //選中的顏色
          labelStyle: TextStyle(fontSize: 16), //選中的樣式
          unselectedLabelColor: Colors.black, //未選中的顏色
          unselectedLabelStyle: TextStyle(fontSize: 14), //未選中的樣式
          indicatorColor: Colors.green, //下劃線顏色
          isScrollable: false, //是否可滑動鹉戚,設(shè)置不可滑動,則是tab的寬度等長
          //tab標(biāo)簽
            tabs: titleTabs, // 設(shè)置標(biāo)題

          //點擊事件
          onTap: (int i) {
            print(i+10);
          },
        ),
        body: new TabBarView(
          controller: mController,
          children:  <Widget>[ // 每個空間對應(yīng)的頁面
        Center(child:Text('Android')),
        Center(child:Text('iOS')),
        Center(child:Text('Web')),
        ],
        ),
      );
  }

  @override
  void dispose() {
    super.dispose();
    mController.dispose(); // 當(dāng)整個頁面dispose時专控,記得把控制器也dispose掉抹凳,釋放內(nèi)存
  }

  // 點擊監(jiān)聽函數(shù)
  _onTabChanged() {
    print(mController.index);
  }
}

6. 總結(jié)

  • 本文全面介紹了Flutter的布局組件中頂部導(dǎo)航欄的實現(xiàn):TabBar + TabBarView + TabController
  • 接下來推出的文章,我將繼續(xù)講解Flutter的相關(guān)知識伦腐,包括使用語法赢底、實戰(zhàn)等,感興趣的讀者可以繼續(xù)關(guān)注我的博客哦:Carson_Ho的Android博客

請點贊柏蘑!因為你們的贊同/鼓勵是我寫作的最大動力幸冻!

相關(guān)文章閱讀
Android開發(fā):最全面、最易懂的Android屏幕適配解決方案
Android開發(fā):史上最全的Android消息推送解決方案
Android開發(fā):最全面辩越、最易懂的Webview詳解
Android開發(fā):JSON簡介及最全面解析方法!
Android四大組件:Service服務(wù)史上最全面解析
Android四大組件:BroadcastReceiver史上最全面解析


歡迎關(guān)注Carson_Ho的簡書嘁扼!

不定期分享關(guān)于安卓開發(fā)的干貨,追求短黔攒、平趁啸、快,但卻不缺深度督惰。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末不傅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赏胚,更是在濱河造成了極大的恐慌访娶,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件觉阅,死亡現(xiàn)場離奇詭異崖疤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)典勇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門劫哼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人割笙,你說我怎么就攤上這事权烧。” “怎么了伤溉?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵般码,是天一觀的道長。 經(jīng)常有香客問我乱顾,道長板祝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任走净,我火速辦了婚禮扔字,結(jié)果婚禮上囊嘉,老公的妹妹穿的比我還像新娘温技。我一直安慰自己革为,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布舵鳞。 她就那樣靜靜地躺著震檩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜓堕。 梳的紋絲不亂的頭發(fā)上抛虏,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機(jī)與錄音套才,去河邊找鬼迂猴。 笑死,一個胖子當(dāng)著我的面吹牛背伴,可吹牛的內(nèi)容都是我干的沸毁。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼傻寂,長吁一口氣:“原來是場噩夢啊……” “哼息尺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起疾掰,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤搂誉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后静檬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炭懊,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年拂檩,在試婚紗的時候發(fā)現(xiàn)自己被綠了侮腹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡广恢,死狀恐怖凯旋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钉迷,我是刑警寧澤至非,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站糠聪,受9級特大地震影響荒椭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舰蟆,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一趣惠、第九天 我趴在偏房一處隱蔽的房頂上張望狸棍。 院中可真熱鬧,春花似錦味悄、人聲如沸草戈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唐片。三九已至,卻和暖如春涨颜,著一層夾襖步出監(jiān)牢的瞬間费韭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工庭瑰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留星持,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓弹灭,卻偏偏與公主長得像督暂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鲤屡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351