在 Material Design 设计准则里,主要提供了两种导航方式:Tab 和 Drawer。 当没有足够的空间来支持 tab 导航时,drawer 提供了另一个方便的选择。

在 Flutter中,我们可以将 Drawer Widget 与 Scaffold 结合使用来创建一个具有 Material Design 风格的 Drawer 布局。

步骤

  • 创建一个 Scaffold

  • 添加一个 drawer

  • 向 drawer 中添加内容

  • 通过编程关闭 drawer

1. 创建一个 Scaffold

为了向应用中添加一个 Drawer,我们需要将其放在 Scaffold Widget 中。 Scaffold Widget 为遵循 Material 设计守则的应用程序提供了一套统一的可视化结构。它同样支持一些特殊的 Material Design 组件,例如 Drawer,AppBar 和 SnackBar 等。

在这个例子中,我们想要创建一个带有 drawerScaffold

  1. Scaffold(
  2. drawer: // We'll add our Drawer here in the next step!
  3. );

2. 添加一个 drawer

我们现在可以在 Scaffold 上添加一个 drawer。虽然 drawer 可以是任何 Widget,但最好还是使用 material library 中的 Drawer Widget,因为这样才符合 Material Design 设计规范。

  1. Scaffold(
  2. drawer: Drawer(
  3. child: // We'll populate the Drawer in the next step!
  4. )
  5. );

3. 向 drawer 中添加内容

既然已经有了一个 Drawer,我们现在就可以向其中添加内容。在这个例子中,我们将使用 ListView。虽然你也可以使用 Column Widget,但是 ListView 在这种情况下将是更好的选择,因为如果内容所占用的空间超出了屏幕的话,它将能够允许用户进行滚动。

我们将使用 DrawerHeader 和两个 ListTile Widget 填充 ListView。有关使用 List 的更多信息,请参阅 list recipes

  1. Drawer(
  2. // Add a ListView to the drawer. This ensures the user can scroll
  3. // through the options in the Drawer if there isn't enough vertical
  4. // space to fit everything.
  5. child: ListView(
  6. // Important: Remove any padding from the ListView.
  7. padding: EdgeInsets.zero,
  8. children: <Widget>[
  9. DrawerHeader(
  10. child: Text('Drawer Header'),
  11. decoration: BoxDecoration(
  12. color: Colors.blue,
  13. ),
  14. ),
  15. ListTile(
  16. title: Text('Item 1'),
  17. onTap: () {
  18. // Update the state of the app
  19. // ...
  20. },
  21. ),
  22. ListTile(
  23. title: Text('Item 2'),
  24. onTap: () {
  25. // Update the state of the app
  26. // ...
  27. },
  28. ),
  29. ],
  30. ),
  31. );

4. 通过编程关闭 drawer

我们经常需要在用户点击某个项目后,就将 Drawer 关掉。那么怎样才能做到这一点呢?请使用 Navigator

当用户打开 Drawer 时,Flutter 会将 drawer Widget 覆盖在当前的导航堆栈上。 因此,要关闭 drawer,我们可以通过调用 Navigator.pop(context) 来实现。

  1. ListTile(
  2. title: Text('Item 1'),
  3. onTap: () {
  4. // Update the state of the app
  5. // ...
  6. // Then close the drawer
  7. Navigator.pop(context);
  8. },
  9. ),

一个完整的例子

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. final appTitle = 'Drawer Demo';
  5. @override
  6. Widget build(BuildContext context) {
  7. return MaterialApp(
  8. title: appTitle,
  9. home: MyHomePage(title: appTitle),
  10. );
  11. }
  12. }
  13. class MyHomePage extends StatelessWidget {
  14. final String title;
  15. MyHomePage({Key key, this.title}) : super(key: key);
  16. @override
  17. Widget build(BuildContext context) {
  18. return Scaffold(
  19. appBar: AppBar(title: Text(title)),
  20. body: Center(child: Text('My Page!')),
  21. drawer: Drawer(
  22. // Add a ListView to the drawer. This ensures the user can scroll
  23. // through the options in the Drawer if there isn't enough vertical
  24. // space to fit everything.
  25. child: ListView(
  26. // Important: Remove any padding from the ListView.
  27. padding: EdgeInsets.zero,
  28. children: <Widget>[
  29. DrawerHeader(
  30. child: Text('Drawer Header'),
  31. decoration: BoxDecoration(
  32. color: Colors.blue,
  33. ),
  34. ),
  35. ListTile(
  36. title: Text('Item 1'),
  37. onTap: () {
  38. // Update the state of the app
  39. // ...
  40. // Then close the drawer
  41. Navigator.pop(context);
  42. },
  43. ),
  44. ListTile(
  45. title: Text('Item 2'),
  46. onTap: () {
  47. // Update the state of the app
  48. // ...
  49. // Then close the drawer
  50. Navigator.pop(context);
  51. },
  52. ),
  53. ],
  54. ),
  55. ),
  56. );
  57. }
  58. }

Drawer Demo