Flutter 創(chuàng)建底部導航的三種方式

Flutter創(chuàng)建底部導航的方式:推薦第三種

一檩淋、BottomNavigationBar + BottomNavigationBarItem

  • 優(yōu)缺點:
    • 實現簡單捅儒,代碼量很少基本就能完成
    • 不能調整item的文字和圖片間距
    • 每次切換頁面會重繪蝠检,不會保存之前的頁面狀態(tài)
具體實現:
///根頁面
class MainPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return MainPageState();
  }
}

class MainPageState extends State <MainPage> {
  int currentIndex = 0;
  final items = [
    BottomNavigationBarItem(icon: Image(image: AssetImage('images/Home.png')), title: Text
      ('首頁'),activeIcon: Image(image:
    AssetImage
      ('images/HomeSelect'
        '.png'))),
    BottomNavigationBarItem(icon: Image(image: AssetImage('images/market_normal.png')),
        title:
    Text("行情"),activeIcon: Image(image: AssetImage('images/market_selected.png'))),
    BottomNavigationBarItem(icon: Image(image: AssetImage('images/transcation_normal.png')),
        title: Text
      ("交易"),activeIcon: Image
          (image:
        AssetImage('images/transcation_selected.png'),)),
    BottomNavigationBarItem(icon: Image(image: AssetImage('images/assets_normal.png')),
        title: Text
      ("資產"),activeIcon: Image(image:
        AssetImage('images/assets_selected.png'),)),
  ];
///4個tabbar頁面
  final bodyLists = [
    HomepageWidget(),
    MarketpageWidget(),
    TranscationpageWidget(),
    AssetspageWidget()
  ];
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold (
      appBar: AppBar(title: Text("切換"),),
      bottomNavigationBar: BottomNavigationBar(
        items: items,
        currentIndex: currentIndex,
        onTap: onTap,
        unselectedItemColor: prefix1.Color(0xFF989D9D),
        selectedItemColor: prefix1.Color(0xFF333333),
        type: BottomNavigationBarType.fixed,
      ),
      body: bodyLists[currentIndex],
    );
  }
  void onTap(int index) {
    setState(() {
      currentIndex = index;
    });
  }
}

每個子頁面代碼都是一樣的介劫,主要是為了測試每個頁面的狀態(tài)

import 'package:flutter/material.dart';

class HomepageWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return HomepageWidgetState();
  }
}

class HomepageWidgetState extends State <HomepageWidget> {
  int count = 0;
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: Center(
        child: Text("首頁 $count",style: TextStyle(color: Colors.blue),),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: addButtonClick,
        child: Icon(Icons.add),
      ),
    );
  }
  void addButtonClick() {
    setState(() {
      count ++;
    });
  }
}
Oct-23-2019 13-59-00.gif

如上圖呼股,我們可以看到當切換界面的時候,之前的狀態(tài)是被重置了的。那么下面介紹該如何保持狀態(tài)。

二乘盖、BottomNavigationBar +Stack + OffStage

  • 優(yōu)缺點
    • 能夠保存頁面的狀態(tài)
    • 程序初始化的時候所有的child都會執(zhí)行initState(有時候我們想要的效果是當點擊tabbar的時候界面再去加載)
    • 使用BottomNavigationBarItem無法調整文字圖片間距
body: Stack(
        children: [
          _stackOffstage(0),
          _stackOffstage(1),
          _stackOffstage(2),
          _stackOffstage(3)
        ],
      ),

 //根據點擊的索引返回widget
  Widget _stackOffstage(int index) {
    return Offstage(
      //If false, the child is included in the tree as normal.
      offstage: currentIndex != index,
      child: TickerMode(
        child: bodyLists[index],
        //If true, then tickers in this subtree will tick.
        enabled: currentIndex == index,
      ),
    );
  }
Oct-23-2019 15-37-09.gif

三哎迄、使用PageView + AutomaticKeepAliveClientMixin

  • 優(yōu)點
    • 可以保存頁面狀態(tài)
    • 每次點擊才會初始化鲜戒,而且只會初始化一次
    • push pop回來widgetState也不會重新initState
var pageController = PageController();

Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold (
      appBar: AppBar(title: Text("切換"),),
      bottomNavigationBar: BottomNavigationBar(
        items: items,
        currentIndex: currentIndex,
        onTap: onTap,
        unselectedItemColor: prefix1.Color(0xFF989D9D),
        selectedItemColor: prefix1.Color(0xFF333333),
        type: BottomNavigationBarType.fixed,
      ),
      body: PageView(
        controller: pageController,
        children: bodyLists,
        onPageChanged:pageControllerTap ,
        physics: NeverScrollableScrollPhysics(),
      ),
    );
  }

  void pageControllerTap(int index) {
    setState(() {
      currentIndex = index;
    });
  }
  void onTap(int index) {
    pageController.jumpToPage(index);
  }

其中子頁面的代碼,需要注意 AutomaticKeepAliveClientMixin, 重寫方法
wantKeepAlive 孵滞,這樣是讓頁面一直保存在內存中。還有一個要注意的點:super.build(context);鸯匹,如果不寫坊饶,當我們使用Navigator.push切換界面的時候,再pop回來殴蓬,HomepageWidgetState還是會執(zhí)行initState匿级,加上super后就不會再有這個問題。

class HomepageWidgetState extends State <HomepageWidget> with AutomaticKeepAliveClientMixin {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print('HomepageWidgetState initState');
  }
  int count = 0;
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    super.build(context); //注意:每個子頁面要寫`super`
    return Scaffold(
      body: Center(
        child: Text("首頁 $count",style: TextStyle(color: Colors.blue),),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: addButtonClick,
        child: Icon(Icons.add),
      ),
    );
  }
  void addButtonClick() {
    setState(() {
      count ++;
    });
  }
//一直保存在內存中
  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

其中PageController是可以控制pageView中要顯示的界面
physics //How the page view should respond to user input. 用戶如何響應染厅,具體行為可以查看源碼痘绎,我們這里可以禁止滑動NeverScrollableScrollPhysics

 [ScrollPhysics], which can be used instead of this class when the default
///    behavior is desired instead.
///  * [BouncingScrollPhysics], which provides the bouncing overscroll behavior
///    found on iOS.
///  * [ClampingScrollPhysics], which provides the clamping overscroll behavior
///    found on Android.
pageView .gif
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肖粮,隨后出現的幾起案子孤页,更是在濱河造成了極大的恐慌,老刑警劉巖涩馆,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件行施,死亡現場離奇詭異,居然都是意外死亡魂那,警方通過查閱死者的電腦和手機蛾号,發(fā)現死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涯雅,“玉大人鲜结,你說我怎么就攤上這事≌栋牛” “怎么了轻腺?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長划乖。 經常有香客問我,道長挤土,這世上最難降的妖魔是什么琴庵? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮仰美,結果婚禮上迷殿,老公的妹妹穿的比我還像新娘。我一直安慰自己咖杂,他們只是感情好庆寺,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诉字,像睡著了一般懦尝。 火紅的嫁衣襯著肌膚如雪知纷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天陵霉,我揣著相機與錄音琅轧,去河邊找鬼。 笑死踊挠,一個胖子當著我的面吹牛乍桂,可吹牛的內容都是我干的。 我是一名探鬼主播效床,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼睹酌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了剩檀?” 一聲冷哼從身側響起憋沿,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谨朝,沒想到半個月后卤妒,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡字币,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年则披,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洗出。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡士复,死狀恐怖,靈堂內的尸體忽然破棺而出翩活,到底是詐尸還是另有隱情阱洪,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布菠镇,位于F島的核電站冗荸,受9級特大地震影響,放射性物質發(fā)生泄漏利耍。R本人自食惡果不足惜蚌本,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望隘梨。 院中可真熱鬧程癌,春花似錦、人聲如沸轴猎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捻脖。三九已至锐峭,卻和暖如春中鼠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背只祠。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工兜蠕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抛寝。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓熊杨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盗舰。 傳聞我的和親對象是個殘疾皇子晶府,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容