自定义 Flutter 中的 Drawer
原文链接:Custom Drawer in Flutter - 原文作者 Abdur Rehman
本文采用意译的方式
当我们创建移动端应用的时候,有两种主要的导航选项:Tabs 和 Drawers。当没有足够的空间来展示 Tabs,那么 Drawers 提供了个不错的选择。
在本文中,我们将创建一个简单的应用来演示怎么实现一个 drawer 挂件和怎么根据我们的设计来自定义 drawer。
让我们着手写代码来实现 Flutter 中的 drawer 挂件。
在 Flutter 中,我们结合 Scaffold 来使用 drawer 挂件,创建一个带有 Material Design drawer 风格的布局。
代码案例
首先,我们将创建一个名为 flutter_drawer 的项目。然后清除所有没用的注释和代码,以便我们容易理解。我们在 simple_drawer_screen.dart 文件中创建一个名为 SimpleDrawerScreen 的类,然后将其挂在 Material() 的 home 属性上。如下所示:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// 这个挂件是我们应用程序的根
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SimpleDrawerScreen(),
);
}
}
创建一个 Scafflod
为了添加一个 drawer 到应用中,我们将其包含在一个 Scaffold 挂件中。这个 scaffold 支持指定的 Material Design 组件,比如 Drawers,AppBars 和 SnackBars。
return Scaffold(
appBar: AppBar(),
drawer: // 这里接下里会添加一个 Drawer
);
添加一个 Drawer
现在,我们将添加一个 drawer 挂件到 Scaffold 中。我们可以传递任意的挂件到 drawer
中,比如 Container 或者 SizeBox 并随后自定义它,但是我们最好是使用库中自带的 Drawer 挂件,它依附于 Material Design。
return Scaffold(
drawer: Drawer(
child: // 接下来会填充 Drawer
),
);
给 Drawer 添加 Items
我们已经在指定位置添加了 drawer,现在给它添加内容。我们将 ListView 作为一个子组件添加到 Drawer 中。当然,我们可以使用一个 Column 挂件。ListView 很好用,因为它确保用户在没有多余的垂直空间展示时候,能够在 drawer 中滚动。
Drawer(
child: ListView(
// 移除 ListView 的所有 padding 值
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Item 1'),
onTap: () {
// 更新应用中的状态
// ...
},
),
ListTile(
title: const Text('Item 2'),
onTap: () {
// 更新应用中的状态
// ...
},
),
],
),
);
输出
当我们运行,上面的代码将创建一个简单且基础 drawer (的页面),如下:

自定义 Drawer
现在,我们为 Drawer 添加些功能,正如我们说的,导航到新页面和自定义它的 UI。
我们最终自定义的 drawer 如下。文末会展示完整的代码。

Drawer Header
我们为 drawer 自定义头部,在这里我们将展示用户信息,并且点击它的话会跳转到个人页面。
/// Drawer 头部 Header
Material(
color: Colors.blueAccent,
child: InkWell(
onTap: (){
/// 在导航前关闭 Drawer
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => UserProfile()),);
},
child: Container(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top,
bottom: 24
),
child: Column(
children: const[
CircleAvatar(
radius: 52,
backgroundImage: NetworkImage(
'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fHNtaWx5JTIwZmFjZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60'
),
),
SizedBox(height: 12,),
Text('Sophia',
style: TextStyle(
fontSize: 28,
color: Colors.white
),),
const Text('@sophia.com',
style: TextStyle(
fontSize: 14,
color: Colors.white
),),
],
),
),
),
),

Drawer 菜单列表
在 Drawer 中,菜单列表很重要,列表中我们展示不同的选项,比如设置,简介等。当我们点击这些选项,它会重定向到指定的页面。
/// Header Menu 项
Column(
children: [
ListTile(
leading: Icon(Icons.home_outlined),
title: Text('Home'),
onTap: (){
/// 在跳转钱关闭 Drawer
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen()),);
},
),
ListTile(
leading: Icon(Icons.favorite_border),
title: Text('Favourites'),
onTap: (){
/// 在跳转钱关闭 Drawer
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => FavouriteScreen()),);
},
),
ListTile(
leading: Icon(Icons.workspaces),
title: Text('Workflow'),
onTap: (){},
),
ListTile(
leading: Icon(Icons.update),
title: Text('Updates'),
onTap: (){},
),
const Divider(color: Colors.black45,),
ListTile(
leading: Icon(Icons.account_tree_outlined),
title: Text('Plugins'),
onTap: (){},
),
ListTile(
leading: Icon(Icons.notifications_outlined),
title: Text('Notifications'),
onTap: (){},
),
],
)

注意:我们很推荐你读一下
flutter中Drawer的官方文档,这很有帮助。Doc。
转载自:https://juejin.cn/post/7369443728962813962