今日應(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用到了兩個組件,BottomNavigationBar和IndexedStack。簡單介紹一下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)
BottomNavigationBar和IndexedStack兩者結(jié)合就能實(shí)現(xiàn)底部導(dǎo)航切換效果,效果如下:

再看下首頁(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只用AppBar和body兩個屬性,那么該Widget就相當(dāng)于原生有的導(dǎo)航欄UIViewController。 -
Scaffold用到BottomNavigationBar,那個該Widget就相當(dāng)于原生的UITabbarController。
有興趣的小伙伴可以看下我的 Flutter學(xué)習(xí)記錄
后記
Scaffold對于我這開始是iOS原生開發(fā)的程序猿來說,還是一個比較牛皮的組件,幾個簡單的屬性(抽屜、懸浮按鈕還沒提呢)賦值就能實(shí)現(xiàn)對于原生來說比較復(fù)雜的頁面,快,太快了。