Flutter导航抽屉菜单插件navigation_drawer_menu的使用

Flutter 导航抽屉菜单插件 navigation_drawer_menu 的使用

Flutter Material Design 导航抽屉菜单

导航抽屉是一种常见的自适应菜单用户界面模式。《Material Design》文档规范了菜单的行为,但这种模式并不仅限于 Material Design。该模式包括一个基本的汉堡菜单,但不仅仅适用于小屏幕。菜单模式适用于所有屏幕尺寸。在较大的宽度屏幕上,你会看到图标和文本;在较小的屏幕上,只会显示图标;在手机上,菜单在正常使用时会消失,并通过汉堡图标滑入。

Hamburger Menu

Beta

该组件目前处于测试阶段,公共接口可能会发生变化。

示例

该示例旨在实现上述的导航抽屉模式。这是一个正在进行的工作,长期目标是符合《Material Design》文档中的行为。欢迎提交修复行为的请求。该示例适用于所有设备形态:桌面、平板(横屏、竖屏)、手机和网页。尝试调整窗口宽度以查看行为的变化。大多数行为已经存在于示例中,目标是创建一个新的组件,可以替代 Scaffold 并允许你快速启动具有此功能的新应用。

注意:如果你只需要一个不适应屏幕的简单抽屉菜单,请查看 这里

Hamburger Menu

Hamburger Menu

Hamburger Menu

运行示例

  1. 在 Visual Studio Code 中打开根文件夹。
  2. 打开终端窗口。
  3. 在根文件夹中运行以下命令(而不是在示例文件夹中):
    flutter create example --platforms=windows,macos,linux
    flutter create --platforms=web
    flutter create --platforms=android
    
  4. 点击 Run -> Start Debugging

NavigationDrawerMenu

这是一个类似于 ListView 的组件。然而,它存在的目的是为了减少构建菜单所需的样板代码,并允许你在菜单中放置任意大小的间隔和标题。示例使用了这一组定义。如果你不想使用这个组件,可以使用 ListView 替代。

final Map<Key, MenuItemContent> menuItems = {
  alarmValueKey: MenuItemContent(
      menuItem: MenuItemDefinition("Alarm", alarmValueKey,
          iconData: Icons.access_alarm)),
  todoValueKey: MenuItemContent(
      menuItem: MenuItemDefinition("Todo", todoValueKey,
          iconData: Icons.ad_units_rounded)),
  photoValueKey: MenuItemContent(
      menuItem: MenuItemDefinition("Photo", photoValueKey,
          iconData: Icons.add_a_photo_outlined))
};

示例代码

import 'package:flutter/material.dart';
import 'package:navigation_drawer_menu/navigation_drawer.dart';
import 'package:navigation_drawer_menu/navigation_drawer_menu.dart';
import 'package:navigation_drawer_menu/navigation_drawer_menu_frame.dart';
import 'package:navigation_drawer_menu/navigation_drawer_state.dart';

const alarmValueKey = ValueKey('Alarm');
const todoValueKey = ValueKey('Todo');
const photoValueKey = ValueKey('Photo');

final Map<Key, MenuItemContent> menuItems = {
  alarmValueKey: MenuItemContent(
      menuItem: MenuItemDefinition("Alarm", alarmValueKey,
          iconData: Icons.access_alarm)),
  todoValueKey: MenuItemContent(
      menuItem: MenuItemDefinition("Todo", todoValueKey,
          iconData: Icons.ad_units_rounded)),
  photoValueKey: MenuItemContent(
      menuItem: MenuItemDefinition("Photo", photoValueKey,
          iconData: Icons.add_a_photo_outlined))
};

const title = 'navigation_drawer_menu Demo';
const menuColor = Color(0xFF424242);

final theme = ThemeData(
    brightness: Brightness.dark,
    textTheme: const TextTheme(bodyText2: TextStyle(color: Color(0xFFFFFFFF))),
    primaryColor: Colors.white,
    backgroundColor: Colors.black);

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final NavigationDrawerState state = NavigationDrawerState();

  [@override](/user/override)
  Widget build(BuildContext materialAppContext) => MaterialApp(
      debugShowCheckedModeBanner: false,
      title: title,
      theme: theme,
      home: Builder(
          builder: (context) => Scaffold(
              appBar: AppBar(
                  title: const Text(title),
                  leading: Builder(
                    builder: (iconButtonBuilderContext) => IconButton(
                      icon: const Icon(Icons.menu),
                      onPressed: () {
                        state.toggle(iconButtonBuilderContext);
                        setState(() {});
                      },
                      tooltip: 'Toggle the menu',
                    ),
                  )),
              drawer: NavigationDrawer(
                menuBuilder: Builder(builder: getMenu),
                menuMode: state.menuMode(context),
              ),
              body: NavigationDrawerMenuFrame(
                body: Builder(
                    builder: (c) => Center(
                        child: state.selectedMenuKey == null
                            ? const Text('No Selection')
                            : Icon(menuItems[state.selectedMenuKey]!
                                .menuItem!
                                .iconData))),
                menuBackgroundColor: menuColor,
                menuBuilder: Builder(builder: getMenu),
                menuMode: state.menuMode(context),
              ))));

  Widget getMenu(BuildContext context) =>
      Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
        NavigationDrawerMenu(
            highlightColor: Theme.of(context).indicatorColor,
            onSelectionChanged: (c, key) {
              state.selectedMenuKey = key;
              state.closeDrawer(c);
              setState(() {});
            },
            menuItems: menuItems.values.toList(),
            selectedMenuKey: state.selectedMenuKey,
            itemPadding: const EdgeInsets.only(left: 5, right: 5),
            buildMenuButtonContent: (menuItemDefinition, isSelected,
                    buildContentContext) =>
                Row(mainAxisAlignment: MainAxisAlignment.center, children: [
                  Icon(menuItemDefinition.iconData,
                      color: isSelected
                          ? Theme.of(buildContentContext).backgroundColor
                          : Theme.of(buildContentContext)
                              .textTheme
                              .bodyText2!
                              .color),
                  if (state.menuMode(context) != MenuMode.Thin)
                    const SizedBox(
                      width: 10,
                    ),
                  if (state.menuMode(context) != MenuMode.Thin)
                    Text(menuItemDefinition.text,
                        style: isSelected
                            ? Theme.of(context).textTheme.bodyText2!.copyWith(
                                color: Theme.of(buildContentContext)
                                    .backgroundColor)
                            : Theme.of(buildContentContext).textTheme.bodyText2)
                ]))
      ]);
}

更多关于Flutter导航抽屉菜单插件navigation_drawer_menu的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter导航抽屉菜单插件navigation_drawer_menu的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现导航抽屉菜单,通常使用Drawer组件。虽然Flutter没有专门的插件叫做navigation_drawer_menu,但你可以使用Flutter内置的Drawer组件来轻松实现导航抽屉菜单。下面是一个简单的示例,展示如何使用Drawer组件创建导航抽屉菜单。

1. 创建导航抽屉菜单

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Navigation Drawer Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Navigation Drawer Example'),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: <Widget>[
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Text(
                'Menu',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 24,
                ),
              ),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('Home'),
              onTap: () {
                Navigator.pop(context); // 关闭抽屉
                // 导航到主页
              },
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('Settings'),
              onTap: () {
                Navigator.pop(context); // 关闭抽屉
                // 导航到设置页面
              },
            ),
            ListTile(
              leading: Icon(Icons.help),
              title: Text('Help'),
              onTap: () {
                Navigator.pop(context); // 关闭抽屉
                // 导航到帮助页面
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: Text('Home Screen'),
      ),
    );
  }
}

2. 解释代码

  • Drawer: Drawer是一个可以从屏幕边缘滑出的面板,通常用于显示导航菜单。
  • ListView: ListView用于在Drawer中显示菜单项。
  • DrawerHeader: DrawerHeader是抽屉顶部的区域,通常用于显示应用程序的徽标或标题。
  • ListTile: ListTile是抽屉中的每个菜单项,可以包含图标、文本和点击事件。

3. 导航到不同页面

你可以在ListTileonTap回调中实现导航逻辑。例如:

onTap: () {
  Navigator.pop(context); // 关闭抽屉
  Navigator.push(context, MaterialPageRoute(builder: (context) => SettingsScreen()));
}
回到顶部