You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DataTable的DataRow长按(onLongPress)时弹出PopMenu

实现DataTable的DataRow长按弹出PopMenu

要在DataTable的DataRow长按位置弹出菜单,可按以下步骤实现:

  1. 绑定DataRow的长按事件:利用DataRow自带的onLongPress属性,直接关联长按处理函数。
  2. 获取长按全局坐标:通过GestureBinding获取长按操作的全局位置,用于定位弹出菜单。
  3. 调用showMenu显示菜单:使用Flutter内置的showMenu方法,传入上下文、位置和菜单选项。

完整代码示例

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

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DataRow LongPress PopMenu',
      home: Scaffold(
        appBar: AppBar(title: const Text('DataTable示例')),
        body: const _DataTableExample(),
      ),
    );
  }
}

class _DataTableExample extends StatefulWidget {
  const _DataTableExample();

  @override
  State<_DataTableExample> createState() => _DataTableExampleState();
}

class _DataTableExampleState extends State<_DataTableExample> {
  final List<Map<String, dynamic>> _data = [
    {'id': 1, 'name': '张三', 'age': 25},
    {'id': 2, 'name': '李四', 'age': 30},
    {'id': 3, 'name': '王五', 'age': 28},
  ];

  // 处理长按弹出菜单逻辑
  void _showPopupMenu(BuildContext context, Map<String, dynamic> rowData) async {
    final position = GestureBinding.instance.pointerEventPosition;
    final result = await showMenu(
      context: context,
      // 基于长按坐标设置菜单位置
      position: RelativeRect.fromLTRB(
        position.dx,
        position.dy,
        MediaQuery.of(context).size.width - position.dx,
        MediaQuery.of(context).size.height - position.dy,
      ),
      items: [
        PopupMenuItem(
          value: 'edit',
          child: const Text('编辑'),
          onTap: () => print('编辑行数据: $rowData'),
        ),
        PopupMenuItem(
          value: 'delete',
          child: const Text('删除'),
          onTap: () {
            setState(() => _data.remove(rowData));
          },
        ),
      ],
    );

    if (result != null) print('选择了菜单选项: $result');
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: DataTable(
        columns: const [
          DataColumn(label: Text('ID')),
          DataColumn(label: Text('姓名')),
          DataColumn(label: Text('年龄')),
        ],
        rows: _data.map((row) {
          return DataRow(
            cells: [
              DataCell(Text(row['id'].toString())),
              DataCell(Text(row['name'])),
              DataCell(Text(row['age'].toString())),
            ],
            onLongPress: () => _showPopupMenu(context, row),
          );
        }).toList(),
      ),
    );
  }
}

关键说明

  • 精准定位菜单:GestureBinding.instance.pointerEventPosition直接获取长按的全局坐标,确保菜单显示在长按位置。
  • 避免菜单超出屏幕:通过RelativeRect.fromLTRB结合屏幕宽高计算位置,防止菜单显示超出可视区域。
  • 灵活处理菜单交互:既可以在PopupMenuItem的onTap中直接绑定操作,也可以通过showMenu的返回值统一处理选择结果。

内容的提问来源于stack exchange,提问作者laterday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:50:09