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


前言

Flutter 作為Google出品的一個(gè)新興的跨平臺(tái)移動(dòng)客戶(hù)端UI開(kāi)發(fā)框架,正在被越來(lái)越多的開(kāi)發(fā)者和組織使用,包括阿里的咸魚(yú)、騰訊的微信等。

示意圖

示意圖

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

示意圖

目錄


1. 簡(jiǎn)介

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


示意圖

2. 作用

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

3. 具體介紹

參數(shù)說(shuō)明如下:

/**
  *  TabBar
  **/
const TabBar({
    Key key,
    @required this.tabs,// 子標(biāo)簽,一般使用Tab對(duì)象,當(dāng)然也可以是其他的Widget
    this.controller,// 控制器,即TabController對(duì)象
    this.isScrollable = false,// 能否滑動(dòng)。false:每個(gè)tab的寬度則等比,true:tab寬度則包裹item
    this.indicatorColor,// 指示器顏色
    this.indicatorWeight = 2.0, // 指示器厚度
    this.indicatorPadding = EdgeInsets.zero, // 底部指示器的Padding
    this.indicator, // 指示器decoration,如邊框等
    this.indicatorSize,// 指示器大小計(jì)算方式 - 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,// 點(diǎn)擊事件
  })

/**
  *  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也會(huì)更新 previousIndex、設(shè)置animation's的value值、重置indexIsChanging為false并且通知監(jiān)聽(tīng)器
    _previousIndex = initialIndex, // 上一個(gè)選中tab的index值,最初與index相同
    _animationController = AnimationController.unbounded( 
      value: initialIndex.toDouble(),
      vsync: vsync,
    ); // 該動(dòng)畫(huà)值表示當(dāng)前TabBar選中的指示器位置以及TabBar和TabBarView的scrollOffsets

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

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

4. 使用說(shuō)明

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

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

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

/**
*  TabBar
*  導(dǎo)航欄標(biāo)題內(nèi)容
**/
// 1. 設(shè)置要顯示的list內(nèi)容(要與TabController的長(zhǎng)度對(duì)應(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, //下劃線(xiàn)顏色
  isScrollable: false, //是否可滑動(dòng),設(shè)置不可滑動(dòng),則是tab的寬度等長(zhǎng)
  //tab標(biāo)簽
  tabs: titleTabs, // 設(shè)置標(biāo)題(上面設(shè)置的內(nèi)容)

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

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

5. 實(shí)例說(shuō)明

本次采用的實(shí)例 = 3個(gè)Tab

示意圖

具體代碼如下:

main.dart

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

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

TabViewDemo.dart

import 'package:flutter/material.dart'; // Material UI組件庫(kù)
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的個(gè)數(shù)
    // 參數(shù)3:動(dòng)畫(huà)效果的異步處理,默認(rèn)格式

    // 添加監(jiān)聽(tīng)器
    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, //下劃線(xiàn)顏色
          isScrollable: false, //是否可滑動(dòng),設(shè)置不可滑動(dòng),則是tab的寬度等長(zhǎng)
          //tab標(biāo)簽
            tabs: titleTabs, // 設(shè)置標(biāo)題

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

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

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

6. 總結(jié)

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

請(qǐng)點(diǎn)贊!因?yàn)槟銈兊馁澩?鼓勵(lì)是我寫(xiě)作的最大動(dòng)力!

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


歡迎關(guān)注Carson_Ho的簡(jiǎn)書(shū)!

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容