原文链接: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(),
);
}
}
为了添加一个 drawer
到应用中,我们将其包含在一个 Scaffold
挂件中。这个 scaffold
支持指定的 Material Design
组件,比如 Drawers
,AppBars
和 SnackBars
。
return Scaffold(
appBar: AppBar(),
drawer: // 这里接下里会添加一个 Drawer
);
现在,我们将添加一个 drawer 挂件到 Scaffold
中。我们可以传递任意的挂件到 drawer
中,比如 Container
或者 SizeBox
并随后自定义它,但是我们最好是使用库中自带的 Drawer 挂件,它依附于 Material Design。
return Scaffold(
drawer: Drawer(
child: // 接下来会填充 Drawer
),
);
我们已经在指定位置添加了 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
添加些功能,正如我们说的,导航到新页面和自定义它的 UI
。
我们最终自定义的 drawer
如下。文末会展示完整的代码。
我们为 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
中,菜单列表很重要,列表中我们展示不同的选项,比如设置,简介等。当我们点击这些选项,它会重定向到指定的页面。
/// 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。