Flutter Tabs(標(biāo)簽欄)

Tabs 一般用于展現(xiàn)多個頁面的內(nèi)容的容器,例如微信的下面標(biāo)簽欄。

常用的組件有:TabBar、TabBarView、TabController(有狀態(tài))、DefaultTabController(無狀態(tài))、BottomNavigationBar(底端欄)。

在 Tabs 里,使用到了動畫效果,因此需要 with 一個類。

// 之前
class HomePageState extends State<HomePage> {
    // ...
}
// 使用 Tabs 之后
class HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
    // ...
}

接著,在 HomePageState 里初始化 Tabs Controller,這里重寫了兩個生命周期函數(shù)。

class HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
    var tabController;      // 先聲明變量

    @override
    void initState() {
        super.initState();
        this.tabController = new TabController(
            vsync: this,    // 動畫效果的異步處理
            length: 3       // tab 個數(shù)
        );
    }
    // 當(dāng)整個頁面 dispose 時(shí),記得把控制器也 dispose 掉,釋放內(nèi)存
    @override
    void dispose() {
        this.tabController .dispose();
        super.dispose();
    }
}

接著,添加 TabBar 和 TabBarView。

Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
            title: new Text('首頁'),
        ),
        body: new TabBarView(
            controller: this.tabController, //配置控制器
            children: [ // Tab 內(nèi)容
                new Text('aaa'),
                new Text('bbb'),
                new Text('ccc'),
            ],
        ),
        // 底端欄是一個 TabBar
        bottomNavigationBar: new Material(
            color: Colors.blue,
            child: new TabBar(
                controller: this.tabController,
                indicatorColor: Colors.white,
                tabs: <Tab>[
                    new Tab(
                        text: '主頁',
                        icon: new Icon(Icons.home),
                    ),
                    new Tab(
                        text: '歷史',
                        icon: new Icon(Icons.history),
                    ),
                    new Tab(
                        text: '書籍',
                        icon: new Icon(Icons.book),
                    ),
                ],
            ),
        )
    );
}

可以看到,在 TabBar 里是設(shè)置控制欄的內(nèi)容,在 TabBarView 里是設(shè)置每個 Tab 的內(nèi)容。而 TabController 是一個用于控制的組件。 TabBar 與 TabBarView 的數(shù)組位置一一對應(yīng)。

TabBar

TabBar是用于顯示 Tab 的菜單信息的。

在 TabBar 里有以下常用屬性:

  • controller → TabController - 控制組件。
  • tabs → List - tabs 列表。
  • indicatorColor → Color - 指示線顏色,就是下面的線條。使用 Colors.transparent 可以讓它消失。
  • unselectedLabelColor → Color - 未選定標(biāo)簽標(biāo)簽的顏色。
  • unselectedLabelStyle → TextStyle - 未選定標(biāo)簽標(biāo)簽的文字樣式。
  • labelStyle → TextStyle - 字體樣式。
  • labelColor → Color - 字體顏色,默認(rèn)白色。
  • isScrollable → bool - 該標(biāo)簽欄是否可以水平滾動,默認(rèn) false。在多個 tab 時(shí)有用。
  • indicatorWeight → double - 指示線的大小,必須大于 0。
  • indicatorSize → TabBarIndicatorSize - 所選標(biāo)簽指標(biāo)的大小,當(dāng)為 Tab 時(shí)會盡可能大,當(dāng)為 Label 時(shí)會盡可能小。
  • indicatorPadding → EdgeInsetsGeometry - 顯示在選定選項(xiàng)卡下方的線的水平填充。


TabBar 沒有可以用于設(shè)置選中項(xiàng)樣式的屬性。那么想設(shè)置選中的樣式怎么弄?可以利用未選中來排除。

 bottomNavigationBar: new Material(
    color: Colors.white,
    child: new TabBar(
        controller: this.tabController,
        unselectedLabelColor: Colors.black38, // <-- 一定要在 labelColor 前面。
        labelColor: Colors.blue,
        indicatorColor: Colors.blue,
        tabs: <Tab>[],
    ),
);

把 TabBar 放在頂端,通過 appBar 的 title 設(shè)置。

appBar: new AppBar(
    title: new Material(                            // <-- 放在這里
        color: Colors.blue,
        child: new TabBar(
            controller: this.tabController,
            indicatorColor: Colors.transparent,
            unselectedLabelColor: Colors.blue[200],
            labelColor: Colors.white,
            tabs: <Tab>[
                new Tab(text: '主頁'),
                new Tab(text: '歷史'),
                new Tab(text: '書籍'),
            ],
        ),
    ),
),

還可以放在 bottom 處,形成一種雙欄效果。

appBar: new AppBar(
    title: new Icon(Icons.menu),
    bottom: new TabBar(
        controller: this.tabController,
        indicatorColor: Colors.transparent,
        unselectedLabelColor: Colors.blue[200],
        labelColor: Colors.white,
        tabs: <Tab>[
            new Tab(text: '主頁'),
            new Tab(text: '歷史'),
            new Tab(text: '書籍'),
        ],
    )
),

TabBarView

TabBarView就是用來展示每個 Tab 的內(nèi)容的,在 TabBarView 的數(shù)組里與 TabBar 的數(shù)組一一映射。

TabBarView 有以下常用屬性:

  • children → List - Tab 內(nèi)容列表。
  • controller → TabController - Tab 控制器。
  • physics → ScrollPhysics - 頁面視圖如何響應(yīng)用戶輸入。

TabController

TabController是 Tab 頁的控制器,用于定義 Tab 標(biāo)簽和內(nèi)容頁的坐標(biāo),還可配置標(biāo)簽頁的切換動畫效果等。

TabController 一般放入有狀態(tài)控件中使用,以適應(yīng)標(biāo)簽頁數(shù)量和內(nèi)容有動態(tài)變化的場景,如果標(biāo)簽頁在 App 中是靜態(tài)固定的格局,則可以在無狀態(tài)控件中加入簡易版的 DefaultTabController 以提高運(yùn)行效率,畢竟無狀態(tài)控件要比有狀態(tài)控件更省資源,運(yùn)行效率更快。

TabController 的使用方式非常直白,它作為 TabBar 和 TabBarView 的控制器使用存在。

class HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
    var tabController;      // 先聲明變量

    @override
    void initState() {
        super.initState();
        this.tabController = new TabController(
            vsync: this,        // 動畫效果的異步處理
            length: 3           // tab 個數(shù)
            initialIndex: 0,    // 起始位置
        );
    }
    // 當(dāng)整個頁面 dispose 時(shí),記得把控制器也 dispose 掉,釋放內(nèi)存
    @override
    void dispose() {
        this.tabController.dispose();
        super.dispose();
    }
}

常用的方法和屬性:

  • animateTo(int index) - 滑動到某個 tab 頁。
  • offset(double val) - 獲取/設(shè)置當(dāng)前 tab 的偏移量(從第一個開始算) 。
  • dispose() - 釋放當(dāng)前 tabController。
  • addListener() - 監(jiān)聽器。
  • indexIsChanging → bool - 返回 tab index 是否已經(jīng)改變了。
new FlatButton(
    child: new Text('點(diǎn)我'),
    onPressed: () {
        this.tabController.animateTo(0);
        print(this.tabController.offset());
    },
),

那么一般當(dāng) tab 索引改變時(shí),會做一些處理,比如網(wǎng)絡(luò)請求什么的,在這里怎么判斷?使用 addListener。

@override
void initState() {
    super.initState();
    this.tabController = new TabController(vsync: this, length: 3);
    this.tabController.addListener(() {
        if (this.tabController.indexIsChanging) {
            print('索引改變');
        }
    });
}

BottomNavigationBar

也可以單獨(dú)使用 BottomNavigationBar,不過這時(shí)候要自己設(shè)置頁面的渲染內(nèi)容。

bottomNavigationBar: new Builder(
    builder: (BuildContext context) {
        return new BottomNavigationBar(
            items: [
                new BottomNavigationBarItem(icon: new Icon(Icons.adb), title: new Text('首頁')),
                new BottomNavigationBarItem(icon: new Icon(Icons.adb), title: new Text('關(guān)于')),
            ],
            onTap: (index) {
                Scaffold.of(context).showSnackBar(
                    new SnackBar(
                        content: new Text('Hello'),
                    ),
                );
            },
        );
    },
)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明AI閱讀 16,211評論 3 119
  • 說到微習(xí)慣,想到去年不知道從什么時(shí)候開始,養(yǎng)成了晚上刷牙的習(xí)慣,這應(yīng)該也算做是一個小小的成就吧。記得當(dāng)時(shí)是牙...
    仙人掌柜閱讀 690評論 0 1
  • 曾偷偷喜歡過一個人 小心翼翼的將他名字放在心里 在無數(shù)個夜晚拿出來復(fù)習(xí) 人群中悄悄靠近他的背影 打球時(shí)主動給他遞過...
    陶小陶_閱讀 318評論 0 0
  • 今兒晚上,先生讓小崽自己裝書包,并嚴(yán)肅的跟小崽說這個學(xué)期起,他再也幫他裝書包了,我在一邊腹誹:"早就應(yīng)該這樣。" ...
    萌萌2020閱讀 754評論 0 51
  • 三月七日沙湖道中遇雨。雨具先去,同行皆狼狽,余獨(dú)不覺。已而遂晴,故作此詞。 莫聽穿林打葉聲,何妨吟嘯且徐行。竹杖芒...
    清泉_9313閱讀 1,952評論 6 7

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