Flutter開發(fā)2:導(dǎo)航欄

底部導(dǎo)航欄 BottomNavigationBar

它是屬于 Scaffold 中的一個(gè)位于底部的控件祭玉,與 BottomNavigationBarItem 配合使用

屬性名 類型 簡介
items List<BottomNavigationBarItem> 底部導(dǎo)航欄展示的內(nèi)容項(xiàng)
onTap ValueChanged<int> 點(diǎn)擊導(dǎo)航欄子項(xiàng)時(shí)的回調(diào)
currentIndex int 當(dāng)前選擇的子項(xiàng)索引
type BottomNavigationBarType 底部導(dǎo)航欄的類型,fixed春畔、shifting兩種
selectedItemColor Color 選中時(shí)子項(xiàng)的顏色
unselectedItemColor Color 未選中時(shí)子項(xiàng)的顏色
selectedLabelStyle TextStyle 選中時(shí)子項(xiàng)文字的style
unselectedLabelStyle TextStyle 未選中時(shí)子項(xiàng)文字的style
fixedColor Color type為fixed時(shí)導(dǎo)航欄的顏色脱货,默認(rèn)使用ThemeData.primaryColor
iconSize double 圖標(biāo)大小

需要注意柄错,BottomNavigationBar如果不指定type秉剑,則當(dāng)items小于4個(gè)時(shí)辰妙,type屬性值為fixed雷恃,大于或等于4個(gè)時(shí),則值會(huì)變?yōu)閟hifting狸吞,通常需要顯式的將type設(shè)置為fixed以達(dá)到期望的效果

BottomNavigationBarItem 屬性

屬性名 類型 簡介
icon Widget 要顯示的圖標(biāo)
title Widget 要顯示的文字
activeIcon Widget 選中時(shí)展示的icon
backgroundColor Color type為shifting時(shí)的背景顏色
 int _currentBottomBarIndex = 0;
 BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '首頁',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.park),
            label: '廣場',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.shopping_cart),
            label: '購物車',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '我的',
          )
        ],
        type: BottomNavigationBarType.fixed,
        selectedItemColor: Colors.purple,
        unselectedItemColor: Colors.grey,
        selectedFontSize: 16,
        unselectedFontSize: 14,
        currentIndex: _currentBottomBarIndex,
        selectedLabelStyle: const TextStyle(color: Colors.purple),
        unselectedLabelStyle: const TextStyle(color: Colors.grey),
        onTap: (index){
          setState(() {
            _currentBottomBarIndex = index;
          });
        },
      ),
WX20220424-113110.png

任意導(dǎo)航欄 TabBar

它是切換Tab頁的入口良瞧,通常會(huì)放到AppBar控件中的bottom屬性中使用瞬雹,也可放到其他布局位置荣赶,其子元素按水平橫向排列布局凤价,一般會(huì)與TabBarView組合使用,形成聯(lián)動(dòng)效果拔创。

屬性名 類型 簡介
tabs List<Widget> 要顯示的Tab列表料仗,通常使用Tab控件
controller TabController 要顯示的文字
isScrollable bool 是否可滾動(dòng)
indicatorColor Color 指示器顏色
indicatorWeight double 指示器厚度
indicatorPadding EdgeInsetsGeometry 底部指示器的Padding
indicator Decoration 指示器decoration,例如邊框等
indicatorSize TabBarIndicatorSize 指示器大小計(jì)算方式
labelColor Color 選中Tab文字顏色
labelStyle TextStyle 選中Tab文字Style
unselectedLabelColor Color 未選中Tab中文字顏色
unselectedLabelStyle TextStyle 未選中Tab中文字style

TabBar + TabBarView

TabBarView是Tab頁的內(nèi)容容器伏蚊,其內(nèi)放置Tab頁的主體內(nèi)容。

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {

  @override
  void initState() {
    super.initState();
    controller = TabController(length: 4,vsync: this);
  }

  TabController controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Widget"),
        bottom: TabBar(
          controller: controller,
            tabs:[
              Tab(text: "社會(huì)心理學(xué)",),
              Tab(text: "發(fā)展心理學(xué)",),
              Tab(text: "變態(tài)心理學(xué)",),
              Tab(text: "健康心理學(xué)",)
            ]
        ),
      ),
      body: TabBarView(
        controller: controller,
        children: <Widget>[
          Icon(Icons.access_time),
          Icon(Icons.accessibility_new),
          Icon(Icons.keyboard),
          Icon(Icons.airline_seat_flat),
        ],
      ),
    );
  }
}

當(dāng)我們不需要通過代碼去手動(dòng)切換Tab頁時(shí)格粪,可使用默認(rèn)的控制器DefaultTabController

TabBar + PageView


保存狀態(tài)

直接使用如上方案躏吊,在每次切換Page 頁時(shí),頁面都會(huì)重新創(chuàng)建帐萎,initState重新執(zhí)行比伏,想要提升性能,達(dá)到我們期望的效果疆导,則需要使用如下步驟保存狀態(tài)

在State類上混入AutomaticKeepAliveClientMixin類
重寫wantKeepAlive方法赁项,并返回true
在頁面的build方法中,調(diào)用super.build

iOS 風(fēng)格導(dǎo)航欄

關(guān)于部分iOS風(fēng)格的控件澈段,可以查看 Cupertino 官方文檔

Flutter 官方正在逐漸完善Cupertino風(fēng)格的控件體系悠菜,但總的來說仍然存在一些問題,目前還不太建議使用败富,這里僅作為介紹悔醋。

CupertinoTabBar + CupertinoTabView 示例

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '頁面框架',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}


class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
      tabBar: CupertinoTabBar(
        items: const [
          BottomNavigationBarItem(label: "首頁", icon: Icon(Icons.home)),
          BottomNavigationBarItem(label: "我的", icon: Icon(Icons.account_box)),
        ],
      ),
      tabBuilder: (BuildContext context, int index) {
        return CupertinoTabView(
          builder: (context) {
            switch (index) {
              case 0:
                return const FirstPage();
                break;
              case 1:
                return const SecondPage();
                break;
              default:
                return const FirstPage();
            }
          },
        );
      },
    );
  }
}

class FirstPage extends StatefulWidget {
  const FirstPage({Key? key}) : super(key: key);

  @override
  _FirstPageState createState() => _FirstPageState();
}

class _FirstPageState extends State<FirstPage> {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold (
      navigationBar: const CupertinoNavigationBar(
        middle: Text("首頁"),
        transitionBetweenRoutes: false,
      ),
      child: Center(
        child: CupertinoButton (
          child: const Text("跳轉(zhuǎn)新頁"),
          onPressed: () {
            Navigator.of(context,rootNavigator: true).push(
                CupertinoPageRoute(
                    builder: (BuildContext context) {
                      return const NewPage();
                    }
                )
            );
          },
        ),
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  const SecondPage({Key? key}) : super(key: key);

  @override
  _SecondPageState createState() => _SecondPageState();
}

class _SecondPageState extends State<SecondPage> {
  @override
  Widget build(BuildContext context) {
    return const CupertinoPageScaffold (
      navigationBar: CupertinoNavigationBar(
        middle: Text("我的"),
      ),
      child: Center(
          child: Text("我的頁面")
      ),
    );
  }
}

class NewPage extends StatelessWidget {
  const NewPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        transitionBetweenRoutes: false,
      ),
      child: Container(
        alignment: Alignment.center,
        child: const Text("新頁面"),
      ),
    );
  }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市兽叮,隨后出現(xiàn)的幾起案子芬骄,更是在濱河造成了極大的恐慌猾愿,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件账阻,死亡現(xiàn)場離奇詭異蒂秘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)淘太,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門姻僧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人琴儿,你說我怎么就攤上這事段化。” “怎么了造成?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵显熏,是天一觀的道長。 經(jīng)常有香客問我晒屎,道長喘蟆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任鼓鲁,我火速辦了婚禮蕴轨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘骇吭。我一直安慰自己橙弱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布燥狰。 她就那樣靜靜地躺著棘脐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪龙致。 梳的紋絲不亂的頭發(fā)上蛀缝,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音目代,去河邊找鬼屈梁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛榛了,可吹牛的內(nèi)容都是我干的在讶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼霜大,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼真朗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起僧诚,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤遮婶,失蹤者是張志新(化名)和其女友劉穎蝗碎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旗扑,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹦骑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了臀防。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眠菇。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖袱衷,靈堂內(nèi)的尸體忽然破棺而出捎废,到底是詐尸還是另有隱情,我是刑警寧澤致燥,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布登疗,位于F島的核電站,受9級(jí)特大地震影響嫌蚤,放射性物質(zhì)發(fā)生泄漏辐益。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一脱吱、第九天 我趴在偏房一處隱蔽的房頂上張望智政。 院中可真熱鬧,春花似錦箱蝠、人聲如沸续捂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牙瓢。三九已至,卻和暖如春床三,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杨幼。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工撇簿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人差购。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓四瘫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親欲逃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子找蜜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Dart 控件 https://api.flutter.dev/flutter/widgets/widgets-l...
    CodingTom閱讀 1,659評(píng)論 0 3
  • 實(shí)現(xiàn)底部導(dǎo)航欄并點(diǎn)擊切換頁面可簡述為有三種方式 TabBar + TabBarView BottomNavigat...
    DDLH閱讀 706評(píng)論 1 0
  • 在Flutter中,Widget是一切的基礎(chǔ)稳析,作為響應(yīng)式渲染洗做,屬于MVVM的實(shí)現(xiàn)機(jī)制弓叛,通過修改數(shù)據(jù),再用setSt...
    蔥花思雞蛋閱讀 1,760評(píng)論 0 4
  • Flutter里面的布局都是由各種widget組成的诚纸,所以有必要熟悉一下各種widget 基礎(chǔ) Widgets 名...
    Observer_觀者閱讀 653評(píng)論 0 3
  • 基礎(chǔ) Widgets Container : 一個(gè)擁有繪制撰筷、定位、調(diào)整大小的 widget畦徘。Row:在水平方向上排...
    吧啦吧閱讀 2,587評(píng)論 0 5