0

I create a function showPopupMenu because I need this multiple times in this project. When I will click an item on showPopupMenu that time I need the clicked position on the main page. How can I do this?

Here is my main page code:

 return MaterialApp(
  home: Scaffold(
      appBar: const CustomToolbar(title: 'Test Screen'),
      body: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Padding(
                padding: EdgeInsets.only(left: 10),
                child: Text('Notice Board',
                    style: TextStyle(
                        fontFamily: 'Montserrat Bold',
                        color: Colors.black)),
              ),
              InkWell(
                  onTapDown: (TapDownDetails tap) {
                    var menus = <String>['Edit', 'Delete'];
                    showPopupMenu(context, tap, menus);
                    //I want to clicked position here
                  },
                  child: const Icon(Icons.more_vert, color: Colors.grey))
            ],
          )
        ],
      )),
);

And here is my showPopupMenu method code:

void showPopupMenu(
BuildContext context, TapDownDetails tap, List<String> menus) async { await showMenu(
context: context,
position: RelativeRect.fromLTRB(
    tap.globalPosition.dx, tap.globalPosition.dy, 0, 0),
items: [
  if (menus.isNotEmpty)
    PopupMenuItem<String>(
        value: menus[0], onTap: () {}, child: Text(menus[0])),
  if (menus.length > 1)
    PopupMenuItem<String>(value: menus[1], child: Text(menus[1])),
  if (menus.length > 2)
    PopupMenuItem<String>(value: menus[2], child: Text(menus[2])),
  if (menus.length > 3)
    PopupMenuItem<String>(value: menus[3], child: Text(menus[3]))
],
elevation: 8.0);}

2 Answers2

0

Try it:

    GestureDetector(
          onTapDown: (TapDownDetails tap) {
            var menus = <String>['Edit', 'Delete'];
              var clickPos = await showPopupMenu(context, tap, menus);
              if (clickPos != null) {
                print("Click at $clickPos");
              }
          },
          child: const Icon(Icons.more_vert, color: Colors.grey),
        )


 Future showPopupMenu(BuildContext context, TapDownDetails tap, List<String> menus, {double buttonHeight = 24, double buttonWidth = 24}) async {
    var dx = tap.globalPosition.dx - (tap.localPosition.dx - buttonWidth);
    var dy = tap.globalPosition.dy - (tap.localPosition.dy - buttonHeight);
    return showMenu(
        context: context,
        position: RelativeRect.fromLTRB(dx, dy, dx, dy),
        items: menus.map((e) => PopupMenuItem<String>(value: e, onTap: () {}, child: Text(e))).toList(),
        elevation: 8.0);
  }
cloudpham93
  • 524
  • 1
  • 4
0

This is the main page widget code

 InkWell(
                onTapDown: (TapDownDetails tap) async {
                  var menus = <String>['Edit', 'Delete'];
                  String clickPos =
                      await showPopupMenus(context, tap, menus);
                  setState(() {
                    print("Click on $clickPos");
                  });
                },
                child: const Icon(Icons.more_vert, color: Colors.grey),
              )

and here is the Constant code

Future<String> showPopupMenus(
    BuildContext context, TapDownDetails tap, List<String> menus) async {
  String _value = "";
  await showMenu(
    context: context,
    position: RelativeRect.fromLTRB(
        tap.globalPosition.dx, tap.globalPosition.dy, 0, 0),
    items: [
      if (menus.isNotEmpty)
        PopupMenuItem<String>(
            value: menus[0], onTap: () {}, child: Text(menus[0])),
      if (menus.length > 1)
        PopupMenuItem<String>(value: menus[1], child: Text(menus[1])),
      if (menus.length > 2)
        PopupMenuItem<String>(value: menus[2], child: Text(menus[2])),
      if (menus.length > 3)
        PopupMenuItem<String>(value: menus[3], child: Text(menus[3]))
    ],
    elevation: 8.0,
  ).then((value) {
    if (value != null) {
      // print("Position $value");
      _value = value;
    }
  });
  return _value;
}

Here I am returning String. If you want to return position(int) then use the code below.
This code is for widget

InkWell(
                onTapDown: (TapDownDetails tap) async {
                  var menus = <String>['Edit', 'Delete'];
                  int clickPos =
                      await showPopupMenus(context, tap, menus);
                  setState(() {
                    print("Click on $clickPos");
                  });
                },
                child: const Icon(Icons.more_vert, color: Colors.grey),
              )

And this code is for the constant

Future<int> showPopupMenus(
    BuildContext context, TapDownDetails tap, List<String> menus) async {
  int _value = -1;
  await showMenu(
    context: context,
    position: RelativeRect.fromLTRB(
        tap.globalPosition.dx, tap.globalPosition.dy, 0, 0),
    items: [
      if (menus.isNotEmpty)
        PopupMenuItem<int>(
            value: 0, onTap: () {}, child: Text(menus[0])),
      if (menus.length > 1)
        PopupMenuItem<int>(value: 1, child: Text(menus[1])),
      if (menus.length > 2)
        PopupMenuItem<int>(value: 2, child: Text(menus[2])),
      if (menus.length > 3)
        PopupMenuItem<int>(value: 3, child: Text(menus[3]))
    ],
    elevation: 8.0,
  ).then((value) {
    if (value != null) {
      // print("Position $value");
      _value = value;
    }
  });
  return _value;
}

I hope this will help you. Thank you