Flutter學(xué)習(xí)之十 Scaffold

今日應(yīng)做的事沒有做,明天再早也是耽誤了。

前言

不知道你們是怎么想的,我在學(xué)習(xí)新的語言開發(fā)UI的時候,都會和自己最熟悉的語言做比較。想對應(yīng)iOS的UITabbarController(底部導(dǎo)航)是哪個?UINavigationController(導(dǎo)航控制器)是哪個?UIViewController(視圖控制器)是哪個?從去年的U3D到現(xiàn)在的Flutter,我剛開始接觸的時候都這么想的。U3D的暫且不談,在Flutter中,有一個組件和上面三者都有關(guān)系,那就是Scaffold(頁面骨架)。

正文

一個完整的路由頁可能會包含導(dǎo)航欄、抽屜菜單(Drawer)以及底部 Tab 導(dǎo)航菜單等。如果每個路由頁面都需要開發(fā)者自己手動去實(shí)現(xiàn)這些,這會是一件非常麻煩且無聊的事。幸運(yùn)的是,Flutter Material 組件庫提供了一些現(xiàn)成的組件來減少我們的開發(fā)任務(wù)。Scaffold 是一個路由頁的骨架,我們使用它可以很容易地拼裝出一個完整的頁面。

構(gòu)造函數(shù)

Scaffold({
  Key? key,
  this.appBar,
  this.body,
  this.floatingActionButton,
  this.floatingActionButtonLocation,
  this.floatingActionButtonAnimator,
  this.persistentFooterButtons,
  this.drawer,
  this.onDrawerChanged,
  this.endDrawer,
  this.onEndDrawerChanged,
  this.bottomNavigationBar,
  this.bottomSheet,
  this.backgroundColor,
  ...
  /// 省略部分
})
  • appBar:是一個Material風(fēng)格的導(dǎo)航欄,通過它可以設(shè)置導(dǎo)航欄標(biāo)題、導(dǎo)航欄菜單、導(dǎo)航欄底部的Tab標(biāo)題等。
  • body:頁面主要內(nèi)容。
  • floating 開頭的是右下角懸浮按鈕,有些電商App內(nèi)容比較多,一般喜歡在右下角加個按鈕,一鍵回到頂部。
  • drawer 相關(guān)的,是抽屜效果。
  • bottomNavigationBar:底部導(dǎo)航,對應(yīng)原生UITabbarController。

舉個栗子

我們要實(shí)現(xiàn)一個App頁面,它包含:

  • 一個導(dǎo)航欄
  • 頁面
  • 底部導(dǎo)航

底部導(dǎo)航代碼:

class TabbarController extends StatefulWidget {
  const TabbarController({Key? key}) : super(key: key);
  @override
  State<TabbarController> createState() => _TabbarControllerState();
}

class _TabbarControllerState extends State<TabbarController> {
  int _selectedIndex = 0;
  List<Widget> pages = <Widget>[
    const HomePage(),
    const UIPage(),
    const AnimationPage(),
    const MePage(),
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _selectedIndex,
        children: pages,
        sizing: StackFit.expand,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: '首頁'),
          BottomNavigationBarItem(icon: Icon(Icons.view_agenda), label: 'UI'),
          BottomNavigationBarItem(icon: Icon(Icons.animation), label: '動畫'),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
        ],
        currentIndex: _selectedIndex,
        fixedColor: Colors.blue,
        type: BottomNavigationBarType.fixed,
        onTap: _onItemTapped,
      ),
    );
  }

  _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }
}

TabbarController用到了兩個組件,BottomNavigationBarIndexedStack。簡單介紹一下BottomNavigationBar,就是類似原生的UITabbarController。

BottomNavigationBar

  • items: 數(shù)組放是按鈕。
  • currentIndex: 當(dāng)前選中。
  • fixedColor:選中的顏色,還有基礎(chǔ)顏色可自行查看構(gòu)造方法。
  • onTap: 點(diǎn)擊事件。

IndexedStack就是里面的Widget是在堆疊的,給定指定下標(biāo)就能顯示對應(yīng)的Widget。

IndexedStack:

  • children:視圖數(shù)組,里面存放堆疊的Widget。
  • index: 需要顯示的Widget下標(biāo)

BottomNavigationBarIndexedStack兩者結(jié)合就能實(shí)現(xiàn)底部導(dǎo)航切換效果,效果如下:

TabbarController.gif

再看下首頁(HomePage())的代碼:

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

  @override
  State<StatefulWidget> createState() {
    return HomePageState();
  }
}

//state 控制widget的改變
class HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('首頁'),
      ),
      body: ListView(
        children: [
          Image.asset(
            'images/top.jpeg',
            height: 240,
            fit: BoxFit.cover,
          ),
          titleSection,
          buttonSection,
          textSection,
        ],
      ),
    );
  }
  /// 省略 titleSection、 buttonSection、textSection的實(shí)現(xiàn)
}

可以看到,首頁用到了組件AppBar,廢話不多說,先看看構(gòu)造函數(shù):

AppBar({
  Key? key,
  this.leading, //導(dǎo)航欄最左側(cè)Widget,常見為抽屜菜單按鈕或返回按鈕。
  this.automaticallyImplyLeading = true, //如果leading為null,是否自動實(shí)現(xiàn)默認(rèn)的leading按鈕
  this.title,// 頁面標(biāo)題
  this.actions, // 導(dǎo)航欄右側(cè)菜單
  this.bottom, // 導(dǎo)航欄底部菜單,通常為Tab按鈕組
  this.elevation = 4.0, // 導(dǎo)航欄陰影
  this.centerTitle, //標(biāo)題是否居中 
  this.backgroundColor,
  ...   //其他屬性見源碼注釋
})

注釋已經(jīng)寫好,也是很簡單,常用的就左右兩側(cè)的按鈕,leading是左側(cè)按鈕,actions是右側(cè)的,是個數(shù)組,便于實(shí)現(xiàn)右側(cè)多按鈕頁面。

總結(jié)

通過上面的對Scaffold的使用,可以得出以下結(jié)論:

  • Scaffold只用AppBarbody兩個屬性,那么該Widget就相當(dāng)于原生有的導(dǎo)航欄UIViewController。
  • Scaffold用到BottomNavigationBar,那個該Widget就相當(dāng)于原生的UITabbarController。
有興趣的小伙伴可以看下我的 Flutter學(xué)習(xí)記錄

后記

Scaffold對于我這開始是iOS原生開發(fā)的程序猿來說,還是一個比較牛皮的組件,幾個簡單的屬性(抽屜、懸浮按鈕還沒提呢)賦值就能實(shí)現(xiàn)對于原生來說比較復(fù)雜的頁面,快,太快了。

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

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

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