Flutter菜单管理插件flutter_menu的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter菜单管理插件 flutter_menu 的使用

flutter_menu 是一个用于Web和桌面应用的响应式UI框架,提供了类似桌面应用的体验。它支持触摸屏和桌面显示器,并且具有多种功能,如菜单项、键盘快捷键、主从视图等。

如何安装

在Web上

为了使Flutter应用程序控制右键单击(上下文菜单),需要在index.html文件中添加以下代码:

<body oncontextmenu="return false;"></body>

在桌面端

无需任何更改。

如何使用

您可以通过BuildContext访问所有变量和函数,方便起见,我们提供了一个扩展方法:

context.appScreen

请注意,AppScreen 必须位于父级 BuildContext 中,而不是当前上下文中。因此,窗格必须是 Builder 函数而不是普通的 Widget,以防止误解错误。

菜单

菜单可以包含多个 MenuItem,每个 MenuItem 可以有自己的 MenuListItem。每个 MenuListItem 可以是一个图标、标题和快捷键,并且有一个回调函数 onPressed()

示例:

MenuItem(
  title: 'File',
  menuListItems: [
    MenuListItem(
      icon: Icons.open_in_new,
      title: 'Open',
      onPressed: () {
        // 处理打开操作
      },
      shortcut: MenuShortcut(key: LogicalKeyboardKey.keyO, ctrl: true),
    ),
    MenuListItem(
      title: 'Close',
      onPressed: () {
        // 处理关闭操作
      },
    ),
    // 更多菜单项...
  ],
)

程序化控制:

context.appScreen.hideMenu(); // 隐藏菜单
context.appScreen.showMenu(); // 显示菜单
context.appScreen.openMenu(); // 打开活动菜单项
context.appScreen.closeMenu(); // 关闭打开的菜单项

检查当前状态:

context.appScreen.isMenuShown(); // 返回菜单是否显示
context.appScreen.isMenuOpen();  // 返回是否有菜单项打开

键盘快捷键

每个 MenuListItem 可以设置一个 MenuShortcutMenuShortcut.key 是一个 LogicalKeyboardKey 类型的物理键。可以选择按住哪些系统键(如 ctrlaltshift)来触发快捷键。

示例:

MenuShortcut(key: LogicalKeyboardKey.keyO, ctrl: true) // Ctrl + O 快捷键

键盘快捷键覆盖层

默认情况下,覆盖层是禁用的,但可以通过编程启用或禁用:

context.appScreen.showShortcutOverlay();  // 显示2秒文本覆盖层
context.appScreen.hideShortcutOverlay();  // 不显示覆盖层

主/从窗格

必须设置主窗格(Master Pane)。如果未提供详细窗格(Detail Pane),则仅显示主窗格。如果设置了主窗格和详细窗格,默认行为是允许用户通过移动垂直线来调整详细窗格的大小。

AppScreen(
  masterPaneFlex: 1,      // 默认=1
  detailPaneFlex: 1,      // 默认=1
  masterPaneMinWidth: 500,  // 默认=500
  detailPaneMinWidth: 500,  // 默认=500
  masterPane: masterPane(),
  detailPane: detailPane(),
)

在紧凑模式下,您可以切换主窗格和详细窗格的显示:

context.appScreen.showOnlyMaster(); // 仅显示主窗格
context.appScreen.showOnlyDetail(); // 仅显示详细窗格

抽屉

AppScreen 有自己的抽屉,类似于 Scaffold 的抽屉。您可以选择只设置一个小尺寸的抽屉,或者为用户提供两个不同的尺寸供选择。

AppDrawer(
  defaultSmall: false,
  largeDrawerWidth: 200,
  largeDrawer: drawer(small: false),
  smallDrawerWidth: 60,
  smallDrawer: drawer(small: true),
)

上下文菜单(右键单击或长按)

您可以为主窗格和详细窗格设置不同的上下文菜单,每个单独的小部件也可以有自己的上下文菜单。

示例:

AppScreen(
  masterContextMenu: ContextMenu(
    width: 150,
    height: 250,
    child: ContextMenuSliver(
      title: 'Master',
      children: [
        masterContextMenuItem(color: 'Red'),
        masterContextMenuItem(color: 'Blue'),
        masterContextMenuItem(color: 'Purple'),
        masterContextMenuItem(color: 'Pink'),
      ],
    ),
  ),
)

完整示例 Demo

以下是一个完整的示例,展示了如何使用 flutter_menu 插件:

import 'package:flutter/material.dart';
import 'package:flutter_menu/flutter_menu.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Menu Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Screen(),
    );
  }
}

class Screen extends StatefulWidget {
  [@override](/user/override)
  _ScreenState createState() => _ScreenState();
}

class _ScreenState extends State<Screen> {
  final ScrollController scrollController = ScrollController();
  String _message = "Choose a MenuItem.";

  void _showMessage(String newMessage) {
    setState(() {
      _message = newMessage;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: AppScreen(
        menuList: [
          MenuItem(title: 'File', menuListItems: [
            MenuListItem(
              icon: Icons.open_in_new,
              title: 'Open',
              onPressed: () {
                _showMessage('File.open');
              },
              shortcut: MenuShortcut(key: LogicalKeyboardKey.keyO, ctrl: true),
            ),
            MenuListItem(
              title: 'Close',
              onPressed: () {
                _showMessage('File.close');
              },
            ),
            MenuListItem(
              title: 'Save',
              onPressed: () {
                _showMessage('File.save');
              },
            ),
          ]),
          MenuItem(title: 'View', isActive: true, menuListItems: [
            MenuListItem(title: 'View all'),
            MenuListItem(title: 'close view'),
            MenuListItem(title: 'jump to'),
            MenuListItem(title: 'go to'),
          ]),
        ],
        masterPane: masterPane(),
        detailPane: detailPane(),
        onBreakpointChange: () {
          setState(() {
            print('Breakpoint change');
          });
        },
      ),
    );
  }

  Builder detailPane() {
    return Builder(
      builder: (BuildContext context) {
        return Container(
          color: Colors.blueGrey[300],
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                SizedBox(height: 20),
                Card(
                  elevation: 12,
                  child: Container(
                    width: 300,
                    height: 50,
                    child: Center(
                        child: Text('DETAIL', style: TextStyle(fontSize: 20))),
                  ),
                ),
                SizedBox(height: 20),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ElevatedButton(
                      onPressed: () {
                        context.appScreen.closeMenu();
                      },
                      child: Text('Close Menu'),
                    ),
                  ],
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ElevatedButton(
                      onPressed: () {
                        context.appScreen.hideMenu();
                      },
                      child: Text('Hide Menu'),
                    ),
                    ElevatedButton(
                      onPressed: () {
                        context.appScreen.showMenu();
                      },
                      child: Text('Show Menu'),
                    ),
                  ],
                ),
                SizedBox(height: 20),
                SizedBox(
                  width: 300,
                  height: 300,
                  child: Container(
                    color: Colors.blueGrey,
                    child: Center(
                        child: Text(_message,
                            textAlign: TextAlign.center,
                            style: TextStyle(fontSize: 40))),
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Builder masterPane() {
    return Builder(
      builder: (BuildContext context) {
        return Container(
          color: Colors.white,
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                SizedBox(height: 20),
                Card(
                  elevation: 12,
                  child: Container(
                    width: 300,
                    height: 50,
                    child: Center(
                        child: Text('MASTER', style: TextStyle(fontSize: 20))),
                  ),
                ),
                SizedBox(height: 80),
                ContextMenuContainer(
                  width: 300,
                  height: 200,
                  menu: ContextMenuSliver(
                    title: 'Widget',
                  ),
                  child: SizedBox(
                    width: 300,
                    height: 300,
                    child: Container(
                      color: Colors.blueGrey,
                      child: Center(
                        child: Text('Right click or longpress me',
                            textAlign: TextAlign.center,
                            softWrap: true,
                            style: TextStyle(fontSize: 30)),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

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

1 回复

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


当然,以下是如何在Flutter项目中使用flutter_menu插件的一个基本示例。flutter_menu插件允许你创建一个可定制的菜单,这在需要展示多个选项或动作时非常有用。不过,请注意,由于这个插件可能不是官方的,并且Flutter生态系统中的插件经常更新,你需要确保安装的是最新版本,并查看最新的文档以获取所有可用功能和配置选项。

首先,你需要在你的pubspec.yaml文件中添加flutter_menu依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_menu: ^最新版本号  # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖。

接下来,你可以在你的Flutter项目中创建一个菜单。以下是一个简单的示例,展示了如何使用flutter_menu来创建一个菜单,并在点击菜单项时执行一些操作:

import 'package:flutter/material.dart';
import 'package:flutter_menu/flutter_menu.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Menu Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  void _onMenuItemClick(int index) {
    switch (index) {
      case 0:
        print("Option 1 clicked");
        break;
      case 1:
        print("Option 2 clicked");
        break;
      case 2:
        print("Option 3 clicked");
        break;
      default:
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Menu Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            showMenu(
              context: context,
              position: RelativeRect.fromLTRB(50, 100, 50, 0),
              items: [
                PopupMenuItem(
                  value: 0,
                  child: Text('Option 1'),
                ),
                PopupMenuItem(
                  value: 1,
                  child: Text('Option 2'),
                ),
                PopupMenuItem(
                  value: 2,
                  child: Text('Option 3'),
                ),
              ],
              onSelected: (value) {
                _onMenuItemClick(value);
              },
            );
          },
          child: Text('Show Menu'),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮。当点击按钮时,会弹出一个菜单,菜单中有三个选项。点击菜单中的任何选项都会在控制台中打印出相应的消息。

请注意,showMenu函数的position参数定义了菜单相对于触发按钮的位置。在这个例子中,我们使用了RelativeRect.fromLTRB来指定一个相对位置,但你可以根据你的需求进行调整。

此外,onSelected回调会在用户选择菜单项时被调用,并传递所选项的索引。在这个例子中,我们根据索引执行不同的操作(在这里只是打印消息)。

请确保你安装了flutter_menu插件的最新版本,并根据需要调整代码。如果flutter_menu插件的API有所变化,请参考其最新的文档。

回到顶部