开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 24 天,点击查看活动详情
Scaffold是使用Flutter必不可少的组件,它提供了很多功能的封装,使得开发更加的便捷。
Scaffold
Scaffold包含导航栏、抽屉菜单以及独步的Tab导航菜单等,是一个多组件的大集合,使用它可以很容易的拼装出一个完整的页面。
class ScaffoldRoute extends StatefulWidget {
@override
_ScaffoldRouteState createState() => _ScaffoldRouteState();
}
class _ScaffoldRouteState extends State<ScaffoldRoute> {
int _selectedIndex = 1;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar( //导航栏
title: Text("App Name"),
actions: <Widget>[ //导航栏右侧菜单
IconButton(icon: Icon(Icons.share), onPressed: () {}),
],
),
drawer: MyDrawer(), //抽屉
bottomNavigationBar: BottomNavigationBar( // 底部导航
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(icon: Icon(Icons.business), title: Text('Business')),
BottomNavigationBarItem(icon: Icon(Icons.school), title: Text('School')),
],
currentIndex: _selectedIndex,
fixedColor: Colors.blue,
onTap: _onItemTapped,
),
floatingActionButton: FloatingActionButton( //悬浮按钮
child: Icon(Icons.add),
onPressed:_onAdd
),
);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;//切换Tabbar
});
}
void _onAdd(){
}
}
AppBar
AppBar是一个Material风格的导航栏,通过它可以设置导航栏标题、菜单地步的Tab标题等。
AppBar({
Key? key,
this.leading, //导航栏最左侧Widget,常见为抽屉菜单按钮或返回按钮。
this.automaticallyImplyLeading = true, //如果leading为null,是否自动实现默认的leading按钮
this.title,// 页面标题
this.actions, // 导航栏右侧菜单
this.bottom, // 导航栏底部菜单,通常为Tab按钮组
this.elevation = 4.0, // 导航栏阴影
this.centerTitle, //标题是否居中
this.backgroundColor,
... //其他属性见源码注释
})
如果Scaffold添加了抽屉菜单,默认情况下,scaffold会自动将AppBar的leading设置为菜单栏按钮,如下:
Scaffold(
appBar: AppBar(
title: Text("App Name"),
leading: Builder(builder: (context) {
return IconButton(
icon: Icon(Icons.dashboard, color: Colors.white), //自定义图标
onPressed: () {
// 打开抽屉菜单
Scaffold.of(context).openDrawer();
},
);
}),
...
)
代码中打开抽屉菜单的方法在ScaffoldState中,通过Scaffold.of(context)可以获取父级最近的Scaffold组件的State对象。
抽屉菜单Drawer
Scaffold的drawer和endDrawer属性可以分别接受一个Widget来作为页面的左右抽屉菜单。如果提供了抽屉菜单,那么当用户手指从屏幕左或右侧向里滑动时,便可以打开抽屉菜单。
class MyDrawer extends StatelessWidget {
const MyDrawer({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Drawer(
child: MediaQuery.removePadding(
context: context,
//移除抽屉菜单顶部默认留白
removeTop: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 38.0),
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: ClipOval(
child: Image.asset(
"imgs/avatar.png",
width: 80,
),
),
),
Text(
"Wendux",
style: TextStyle(fontWeight: FontWeight.bold),
)
],
),
),
Expanded(
child: ListView(
children: <Widget>[
ListTile(
leading: const Icon(Icons.add),
title: const Text('Add account'),
),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('Manage accounts'),
),
],
),
),
],
),
),
);
}
}
抽屉菜单通常将Drawer组件作为根节点,它实现了Material风格的菜单面板,MediaQuery.removePadding可以移除Drawer默认的一些留白(默认顶部留白和手机状态栏登高的留白),可以传递不同的参数来看看实际效果。抽屉菜单页顶部和底部组成,顶部由用户头像和昵称组成,底部是一个菜单列表,用ListView来实现。
FloatingActionButton
FloatingActionButton是Material设计规范中的一种特殊Button,通常悬浮在页面的某一个位置作为常用动作的快捷入口。可以通过Scaffold的floatingActionButton属性来设置一个FloatingActionButton,同时通过floatingActionButtonLocation属性来指定其页面中悬浮的位置。
底部Tab导航栏
我们可以通过Scaffold的buttomNavigationBar属性设置底部导航,通过Material组件库提供的BottomNavigationBar和BottomNavigationBarItem两种组件来实现Material风格的底部导航栏。Material组件库提供了一个BottomAppBar组件,它可以和FloatingActionButton配合实现这种打洞效果:
bottomNavigationBar: BottomAppBar(
color: Colors.white,
shape: CircularNotchedRectangle(), // 底部导航栏打一个圆形的洞
child: Row(
children: [
IconButton(icon: Icon(Icons.home)),
SizedBox(), //中间位置空出
IconButton(icon: Icon(Icons.business)),
],
mainAxisAlignment: MainAxisAlignment.spaceAround, //均分底部导航栏横向空间
),
)
打洞位置取决于FloatingActionButton的位置,上面FloatingActionButton的位置为:
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
所以打洞位置在底部导航栏在正中间。
BottomAppBar的shape属性决定洞的外形,CircularNotchedRectangle实现了一个圆形的外形,也可以自定义外形。
页面body
Scaffold的Body部分,可以接收一个Widget,可以传任意的Widget。