点击Flutter图标按钮小部件时显示弹出菜单

3

我已经制作了一个警报对话框,用户可以在其中更新其个人资料。其中有图片容器和图标按钮小部件。 我想要的是,当用户单击图标按钮时,会显示弹出菜单,并提供添加/删除图像选项。以下是我的警报对话框代码:

showDialog<void>(
  builder: (BuildContext context) {
    return AlertDialog(
      title: Text('Update details'),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
      content: StatefulBuilder(
        builder: (context, setState) { return Container(
          width: 400,
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                Stack(
                    alignment: Alignment.center,
                    children: [
                      Container(
                          width: 100.0,
                          height: 100.0,
                          decoration: new BoxDecoration(
                              shape: BoxShape.circle,
                              image: new DecorationImage(
                                  fit: BoxFit.cover,
                                  colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
                                  image: data != null ? MemoryImage(data) : AssetImage("web/icons/contactsDefaultImage.png")
                              )
                          )
                      ),
                      IconButton(icon: Icon(Icons.edit), onPressed: () async {
                         //display option here
                         _showPopupMenu();
                      })
                    ]),
                Container(
                  child: TextFormField(
                    decoration: InputDecoration(
                        labelText: 'name'
                    ),
                  ),
                ),
                TextFormField(
                  decoration: InputDecoration(
                      labelText: 'email'
                  ),
                ),
              ],
            ),
          ),
        );},
      ),
      actions: <Widget>[
        FlatButton(
          child: Text('Cancel'),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
        FlatButton(child: Text('Save'),
          onPressed: () {
          // save
          },
        )
      ],
    );
  },
);

我试过使用showMenu来实现,但由于位置必须硬编码,所以我不想使用它。 我尝试过:
void _showPopupMenu() async {
await showMenu(
  context: context,
  position: RelativeRect.fromLTRB(100, 100, 100, 100),
  items: [
    PopupMenuItem(
      child: Text("add"),
    ),
    PopupMenuItem(
      child: Text("remove"),
    ),
  ],
  elevation: 8.0,
);

现在,我想知道如何在图标按钮被点击时显示它(而不是硬编码值)。是否有另一种方法来实现它,即不使用showMenu。


你能详细说明一下你想要什么吗?请发出你的尝试。 - Osama Abdullah
对不起,我已经更新了问题。 - Rahul Singh
你找到解决方案了吗? - spamup
4个回答

14

你可以编写这样的方法,并在你的图标按钮上调用它的 onPressed 属性

showPopupMenu(){
    showMenu<String>(
      context: context,
      position: RelativeRect.fromLTRB(25.0, 25.0, 0.0, 0.0),  //position where you want to show the menu on screen
      items: [
        PopupMenuItem<String>(
            child: const Text('menu option 1'), value: '1'),
        PopupMenuItem<String>(
            child: const Text('menu option 2'), value: '2'),
        PopupMenuItem<String>(
            child: const Text('menu option 3'), value: '3'),
      ],
      elevation: 8.0,
    )
    .then<void>((String itemSelected) {

      if (itemSelected == null) return;

      if(itemSelected == "1"){
        //code here
      }else if(itemSelected == "2"){
        //code here
      }else{
        //code here
      }

    });
}

编辑:(显示用户点击位置的菜单)

我们可以这样拥有一个方法 -

void showPopUpMenuAtTap(BuildContext context, TapDownDetails details) {
  showMenu(
    context: context,
    position: RelativeRect.fromLTRB(
      details.globalPosition.dx,
      details.globalPosition.dy,
      details.globalPosition.dx,
      details.globalPosition.dy,
    ),
    // other code as above
  );
}

然后像这样使用GestureDetector -

GestureDetector(
  child: const Icon(Icons.menu),
  onTapDown: (details) => showPopUpMenuAtPosition(context, details),
);

感谢你。但请再次查看问题。 - Rahul Singh
我已经完成了,但是由于位置的值是硬编码的,我不想使用它。 - Rahul Singh
你有关于@RahulSingh位置的任何解决方案吗? - Adnan haider
@Adnanhaider,我已编辑答案以包括如何在用户点击时显示菜单。 - Jigar Patel
如果你们中的任何人来这里在onLongPress字段上进行“相对定位”,那么你必须先将点击位置的详细信息从onTapDown发送到你先前声明的某个变量。稍后,你可以通过这个变量获取详细信息。 - KHAN
显示剩余2条评论

4

如果您想重复使用按钮而不是使用手势检测器的解决方案:

创建一个键并将按钮分配给该键。然后:

TextButton(
          key: _accKey,
          text: "Account",
          onPressed: () {
            final RenderBox renderBox =
                _accKey.currentContext?.findRenderObject() as RenderBox;
            final Size size = renderBox.size;
            final Offset offset = renderBox.localToGlobal(Offset.zero);

            showMenu(
                context: context,
                position: RelativeRect.fromLTRB(
                    offset.dx,
                    offset.dy + size.height,
                    offset.dx + size.width,
                    offset.dy + size.height),
                items: [
                  PopupMenuItem<String>(
                      child: const Text('menu option 1'), value: '1'),
                  PopupMenuItem<String>(
                      child: const Text('menu option 2'), value: '2'),
                  PopupMenuItem<String>(
                      child: const Text('menu option 3'), value: '3'),
                ]);
          }),

2
你可以创建一个关键字 GlobalKey _accKey = GlobalKey(); - Winston Rodrigues
关于使用GlobalKey计算Renderbox大小不被鼓励,可以通过BuildContext实现。顺便说一下,这个解决方案是正确的。谢谢。 - abdullah_bd

3

谢谢您的建议,但我已经更新了我的问题,请您再次查看。 - Rahul Singh

1
你要查找的是showdialog和alertdialog。
Void<String> testdialog(BuildContext context) {
return showDialog(
    barrierDismissible: false,
    context: context,
    builder: (context) {
      return StatefulBuilder(builder: (context, setState) {
        return AlertDialog(
            title: ....

谢谢您的回答。我已经更新了我的问题,请再次查看。我不能使用警告对话框。 - Rahul Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接