上下文菜单

用于在右键单击或长按时显示上下文菜单的包。

? 安装

dependencies:
  context_menus: ^0.1.0

⚙ 导入

import 'package:context_menus/context_menus.dart';

?️ 用法

要开始使用,请将 `ContextMenuOverlay` 包装到您的主应用程序或最顶层的视图中。

return ContextMenuOverlay(
  child: MaterialApp(...)
);

然后,您可以使用 `ContextMenuRegion` 小部件来包装那些应该触发上下文菜单的 Widget 树的部分。

return ContextMenuRegion(
  enableLongPress: false,
  // LinkContextMenu is an example menu, provided with this package
  contextMenu: LinkContextMenu(url: 'https://flutterdart.cn'),
  child: TextButton(onPressed: () {}, child: Text("https://flutterdart.cn")),
),

`ContextMenuRegion` 会监听右键单击和(可选的)长按事件。它需要一个 `contextMenu` 小部件,该小部件将在触发其中一个输入事件时显示。

虽然此包提供了一些默认菜单、按钮以及一个用于样式设置的系统,但**重要的是要注意 `contextMenu` 可以是您喜欢的任何小部件。**您可以自由地用自己的菜单内容替换所有这些,而仅依赖插件来管理定位和可见性。

? 自定义菜单

通用上下文菜单 (GenericContextMenu)

创建自定义菜单的最简单方法是使用 `GenericContextMenu`。只需向其传递 `ContextMenuButtonConfig` 列表,它将使用内置的 `ContextMenuButton` 和 `ContextMenuCard` 小部件创建菜单。

/// Custom Context Menu for an Image
ContextMenuRegion(
  contextMenu: GenericContextMenu(
    buttonConfigs: [
      ContextMenuButtonConfig(
        "View image in browser",
        onPressed: () => launch(_testImageUrl),
      ),
      ContextMenuButtonConfig(
        "Copy image path",
        onPressed: () => Clipboard.setData(ClipboardData(text: _testImageUrl)),
      )
    ],
  ),
  child: Image.network(_testImageUrl),
),

使用 `GenericContextMenu` 时,按钮的视觉样式将由 `ContextMenuOverlay.buttonStyle` 属性决定,但也可以通过 `GenericContextMenu.buttonStyle` 进行覆盖。

ContextMenuStateMixin

创建自定义菜单的另一种简单方法是创建一个 `StatefulWidget` 并使用 `ContextMenuStateMixin` 以及 `cardBuilder` 和 `buttonBuilder` 代理。

您可以在现有 `LinkContextMenu` 中看到这一点。

class _LinkContextMenuState extends State<LinkContextMenu> with ContextMenuStateMixin {
  @override
  Widget build(BuildContext context) {
    // cardBuilder is provided to us by the mixin, we must pass it a list of children to layout
    return cardBuilder.call(
      context,
      [
        // buttonBuilder is also provided by the mixin, use it to build each btn
        buttonBuilder.call(
          context,
          // button builder needs a config, so it knows how to setup the btn
          ContextMenuButtonConfig(
            "Open link in new window",
            icon: widget.useIcons ? Icon(Icons.link, size: 18) : null,
            onPressed: () => handlePressed(context, _handleNewWindowPressed),
          ),
        ),
        buttonBuilder.call(
          context,
          ContextMenuButtonConfig(
            "Copy link address",
            icon: widget.useIcons ? Icon(Icons.copy, size: 18) : null,
            onPressed: () => handlePressed(context, _handleClipboardPressed),
          ),
        )
      ],
    );
  }

在上面的示例中,您可以直接提供自己的 Card 和 Buttons,而不是使用构建器,但构建器为您提供了几个优势:

  • 您可以全局样式化所有菜单,方法是编辑 `ContextMenuOverlay` 上的构建器。
  • 所有按钮都会在触发时自动关闭上下文菜单,这是标准行为。
  • 您的自定义菜单将匹配此包附带的 `LinkMenu` 和 `GenericContextMenu`。

提供您自己的小部件

如果您只想使用自己的一组菜单并跳过构建器,只需直接传递即可。

ContextMenuRegion(
  contextMenu: Container(width: 150, child: Column(children: [ ... ])),
  child: ...,
),

请注意,如果您从头开始提供自己的菜单,您将负责设置菜单的水平约束,并在按下项目时关闭菜单。此时,插件将仅处理内容靠近鼠标的定位,并在右键单击或长按时显示内容。

✨ ️样式

您有三种修改样式的选项:

  • 将 `ContextMenuButtonStyle` 传递给 `ContextMenuOverlay` 进行小的样式调整。
  • 使用您自己的 `cardBuilder` 或 `buttonBuilder` 代理以获得更多控制。
  • 直接传递您自己的自定义菜单小部件以获得完全控制。

对于基本样式,只需将按钮样式值传递给 `ContextMenuOverlay`。

return ContextMenuOverlay(
    buttonStyle: ContextMenuButtonStyle(
      fgColor: Colors.green,
      bgColor: Colors.green.shade100,
      hoverFgColor: Colors.green,
      hoverBgColor: Colors.green.shade200,
    ),
    child: MaterialApp(...);
}

为了获得更多控制,您可以覆盖 `cardBuilder` 和 `buttonBuilder` 代理,并选择性地使用提供的样式值。

return ContextMenuOverlay(
  /// Make a custom background
  cardBuilder: (_, children) => Container(color: Colors.purple.shade100, child: Column(children: children)),
  /// Make custom buttons
  buttonBuilder: (_, config, [__]) => TextButton(
    onPressed: config.onPressed,
    child: Container(width: double.infinity, child: Text(config.label)),
  ),
  child: MaterialApp( ... ),
);

如上所述,您始终可以直接将自定义菜单提供给 `ContextMenuRegion`,从而完全绕过提供的样式系统。

?️ 手动控制

如果您想手动显示或关闭菜单,可以查找覆盖层并直接控制它。

ContextMenuOverlay.of(context).show(Container(width: 100, height: 100, color: Colors.red))
...
ContextMenuOverlay.of(context).hide();

这也可以通过 `BuildContext` 上的快捷方式扩展来表达。

context.contextMenuOverlay.close();

? Bug/需求

如果您遇到任何问题,请打开一个 issue。如果您觉得库缺少某个功能,请在 Github 上提交一个 ticket,我们将进行审查。欢迎提交 Pull Request。

? 许可证

MIT 许可

GitHub

查看 Github