ByteNoteByteNote

字节笔记本

2026年2月19日

Flutter WPopupMenu:仿微信聊天长按弹出菜单组件

当微信的交互细节成为行业标杆,我们不禁要问:为什么一个看似简单的长按菜单,能让无数开发者反复琢磨?Flutter 生态中,WPopupMenu 用一行代码给出了答案。

WPopupMenu 简介

WPopupMenu 是一个 Flutter 组件库,用于实现类似微信聊天界面的长按弹出菜单效果。它支持长按或单击触发,可自定义菜单项和样式,是构建聊天类应用的利器。

核心定位:可能是目前最好用的仿微信聊天长按弹出框

核心特性

  • 双触发模式:支持长按(longPress)和单击(singleTap)两种触发方式
  • 智能布局:自动计算菜单位置,避免超出屏幕边界
  • 分页显示:当菜单项超过5个时自动分页,与微信逻辑一致
  • 高度可定制:支持自定义菜单项样式、颜色、图标等
  • 简洁 API:只需包裹目标 Widget 即可使用

安装方法

pubspec.yaml 中添加依赖:

yaml
dependencies:
  w_popup_menu: ^最新版本

然后执行:

bash
flutter pub get

使用示例

基础用法

dart
import 'package:w_popup_menu/w_popup_menu.dart';

WPopupMenu(
  onValueChanged: (int value) {
    // 处理选中项
    print('选中了第 $value 项');
  },
  actions: ['转发', '复制', '删除', '收藏'],
  child: Container(
    padding: EdgeInsets.all(12),
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(4),
    ),
    child: Text('长按我'),
  ),
)

构造函数参数

参数类型必填说明
onValueChangedFunction(int)选中回调,返回选中项索引,取消返回 null
actionsList菜单项文案列表
childWidget被包裹的目标组件
pressTypePressType触发方式,默认 longPress
pageMaxChildCountint每页最多显示项数,默认 5

触发方式设置

dart
// 长按触发(默认)
WPopupMenu(
  pressType: PressType.longPress,
  // ...
)

// 单击触发
WPopupMenu(
  pressType: PressType.singleTap,
  // ...
)

完整示例代码

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

class ChatMessage extends StatelessWidget {
  final String message;

  const ChatMessage({Key? key, required this.message}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return WPopupMenu(
      onValueChanged: (int? value) {
        if (value != null) {
          switch (value) {
            case 0:
              _forwardMessage();
              break;
            case 1:
              _copyMessage();
              break;
            case 2:
              _deleteMessage();
              break;
            case 3:
              _favoriteMessage();
              break;
          }
        }
      },
      actions: ['转发', '复制', '删除', '收藏'],
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        decoration: BoxDecoration(
          color: Color(0xFF95EC69),
          borderRadius: BorderRadius.circular(4),
        ),
        child: Text(message),
      ),
    );
  }

  void _forwardMessage() => print('转发');
  void _copyMessage() => print('复制');
  void _deleteMessage() => print('删除');
  void _favoriteMessage() => print('收藏');
}

实现原理

WPopupMenu 的核心实现基于 Flutter 的 OverlayCustomPainter

  1. 位置计算:通过 RenderBox 获取目标 Widget 的位置和大小
  2. 智能定位:根据屏幕边界自动调整菜单显示位置
  3. 遮罩层:使用 ModalBarrier 实现点击空白处关闭
  4. 动画效果:内置淡入淡出和缩放动画

注意事项

  • 菜单项过多时会自动分页,每页默认最多 5 个
  • 最后一页不足 5 个时会平分空间(与微信一致)
  • 在屏幕边缘时会自动调整菜单位置避免被截断

源码地址

适用场景

  • 聊天应用消息操作菜单
  • 列表项快捷操作
  • 图片/文件预览操作
  • 任何需要上下文菜单的场景

总结

WPopupMenu 是一个轻量但功能完善的 Flutter 弹出菜单组件,其优势包括:

  • 微信级体验:交互逻辑与微信保持一致
  • 开箱即用:一行代码即可实现复杂效果
  • 高度灵活:支持多种自定义配置
  • 智能适配:自动处理边界和分页

对于需要实现聊天类或列表操作菜单的 Flutter 开发者来说,这是一个值得尝试的组件。

分享: