Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dart 如何打开弹出菜单按钮?_Dart_Flutter - Fatal编程技术网

Dart 如何打开弹出菜单按钮?

Dart 如何打开弹出菜单按钮?,dart,flutter,Dart,Flutter,如何从第二个小部件打开弹出菜单 final button = new PopupMenuButton( itemBuilder: (_) => <PopupMenuItem<String>>[ new PopupMenuItem<String>( child: const Text('Doge'), value: 'Doge'), new PopupMenuItem<Str

如何从第二个小部件打开弹出菜单

final button = new PopupMenuButton(
    itemBuilder: (_) => <PopupMenuItem<String>>[
          new PopupMenuItem<String>(
              child: const Text('Doge'), value: 'Doge'),
          new PopupMenuItem<String>(
              child: const Text('Lion'), value: 'Lion'),
        ],
    onSelected: _doSomething);

final tile = new ListTile(title: new Text('Doge or lion?'), trailing: button);
final按钮=新建弹出菜单按钮(
itemBuilder:(\u)=>[
新PopupMenuItem(
子项:常量文本('Doge'),值:'Doge'),
新PopupMenuItem(
子项:const Text('Lion'),值:'Lion'),
],
当选:_doSomething);
最终平铺=新列表平铺(标题:新文本('Doge或lion?'),尾随:按钮);

我想通过点击
磁贴打开
按钮的菜单
,我认为没有办法实现这种行为。虽然您可以将
onTap
属性附加到互动程序,但无法从“外部”访问菜单按钮


您可以采用的一种方法是使用它们,因为它们看起来像ListTiles,并且易于修改和编辑

我找到了你问题的答案。您可以为PopupMenuButton提供一个子按钮,它可以是包括ListTile的任何小部件(请参见下面的代码)。唯一的问题是弹出菜单在ListTile的左侧打开

final popupMenu = new PopupMenuButton(
  child: new ListTile(
    title: new Text('Doge or lion?'),
    trailing: const Icon(Icons.more_vert),
  ),
  itemBuilder: (_) => <PopupMenuItem<String>>[
            new PopupMenuItem<String>(
                child: new Text('Doge'), value: 'Doge'),
            new PopupMenuItem<String>(
                child: new Text('Lion'), value: 'Lion'),
          ],
  onSelected: _doSomething,
)
final popupMenu=新建PopupMenuButton(
孩子:新的ListTile(
标题:新文本(“狗还是狮子”),
尾随:常量图标(图标。更多垂直),
),
itemBuilder:(\u)=>[
新PopupMenuItem(
子项:新文本('Doge'),值:'Doge'),
新PopupMenuItem(
子项:新文本('Lion'),值:'Lion'),
],
当选:_doSomething,
)

这是可行的,但不雅观(与上面Rainer的解决方案存在相同的显示问题:

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey _menuKey = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    final button = new PopupMenuButton(
        key: _menuKey,
        itemBuilder: (_) => <PopupMenuItem<String>>[
              new PopupMenuItem<String>(
                  child: const Text('Doge'), value: 'Doge'),
              new PopupMenuItem<String>(
                  child: const Text('Lion'), value: 'Lion'),
            ],
        onSelected: (_) {});

    final tile =
        new ListTile(title: new Text('Doge or lion?'), trailing: button, onTap: () {
          // This is a hack because _PopupMenuButtonState is private.
          dynamic state = _menuKey.currentState;
          state.showButtonMenu();
        });
    return new Scaffold(
      body: new Center(
        child: tile,
      ),
    );
  }
}
class\u MyHomePageState扩展状态{
最终全局键=新全局键();
@凌驾
小部件构建(构建上下文){
最终按钮=新弹出菜单按钮(
关键:梅努基,
itemBuilder:(\u)=>[
新PopupMenuItem(
子项:常量文本('Doge'),值:'Doge'),
新PopupMenuItem(
子项:const Text('Lion'),值:'Lion'),
],
当选:({});
最终瓷砖=
新建ListTile(标题:新建文本('Doge或lion?')),尾随:按钮,onTap:(){
//这是一次黑客攻击,因为PopupMenuButtonState是私有的。
动态状态=_menuKey.currentState;
state.showButtonMenu();
});
归还新脚手架(
正文:新中心(
孩子:瓦片,
),
);
}
}

我怀疑你实际上想要的是或跟踪的东西——将标签与控件关联并使标签可点击的能力——这是颤振框架中缺少的功能。

我认为最好这样做,而不是显示弹出菜单按钮

void _showPopupMenu() async {
  await showMenu(
    context: context,
    position: RelativeRect.fromLTRB(100, 100, 100, 100),
    items: [
      PopupMenuItem<String>(
          child: const Text('Doge'), value: 'Doge'),
      PopupMenuItem<String>(
          child: const Text('Lion'), value: 'Lion'),
    ],
    elevation: 8.0,
  );
}
然后_showPopupMenu将像

_showPopupMenu(Offset offset) async {
    double left = offset.dx;
    double top = offset.dy;
    await showMenu(
    context: context,
    position: RelativeRect.fromLTRB(left, top, 0, 0),
    items: [
      ...,
    elevation: 8.0,
  );
}
将包用作库

在您的
pubspec.yaml
依赖项中添加
弹出菜单:^1.0.5
。然后导入它:

import 'package:popup_menu/popup_menu.dart';
首先,您应该在代码中的某个位置设置上下文。如下所示:

PopupMenu.context = context;
然后创建一个
showPopup
小部件并传递所需的参数:

 void showPopup(Offset offset) {
    PopupMenu menu = PopupMenu(
        // backgroundColor: Colors.teal,
        // lineColor: Colors.tealAccent,
        maxColumn: 3,
        items: [
          MenuItem(title: 'Copy', image: Image.asset('assets/copy.png')),
          MenuItem(title: 'Mail', image: Icon(Icons.mail, color: Colors.white)),
          MenuItem(title: 'Power',image: Icon(Icons.power, color: Colors.white,)),
        ],
        onClickMenu: onClickMenu,
        stateChanged: stateChanged,
        onDismiss: onDismiss);
    menu.show(rect: Rect.fromPoints(offset, offset));
  }

  void stateChanged(bool isShow) {
    print('menu is ${isShow ? 'showing' : 'closed'}');
  }

  void onClickMenu(MenuItemProvider item) {
    print('Click menu -> ${item.menuTitle}');
  }

  void onDismiss() {
    print('Menu is dismiss');
  }
这是打开的弹出窗口

  @override
  Widget build(BuildContext context) {

  PopupMenu.context = context;  // This is the set context

    return Scaffold(
      appBar: AppBar(
        title: Text('Show Popup')),
      body: Stack(
        children: <Widget>[
          ListView.builder(
            itemCount: list.length,
            itemBuilder: (context, index) {
             return MaterialButton(
                child: GestureDetector(
                  onTapUp: (TapUpDetails details) {
                    showPopup(details.globalPosition);
                  },
                  child: ListTile(
                    leading: IconButton(
                      icon: Icon(Icons.restaurant_menu),
                    ),
                    title: Text("Select your categories"),
                    subtitle: Text("Sub Title"),
                    // onTap: showPopup,
                  ),
                ),

              );
            },
          ),
        ],
      ),
    );
  }
@覆盖
小部件构建(构建上下文){
PopupMenu.context=context;//这是设置的上下文
返回脚手架(
appBar:appBar(
标题:文本(“显示弹出窗口”),
主体:堆栈(
儿童:[
ListView.builder(
itemCount:list.length,
itemBuilder:(上下文,索引){
返回物料按钮(
儿童:手势检测器(
onTapUp:(TapUpDetails){
显示弹出窗口(详细信息。全局位置);
},
孩子:ListTile(
领先:IconButton(
图标:图标(图标。餐厅菜单),
),
标题:文本(“选择您的类别”),
副标题:正文(“副标题”),
//onTap:showPopup,
),
),
);
},
),
],
),
);
}

屏幕截图:


完整代码:

类MyPage扩展了无状态小部件{
最终全局键=全局键();
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
行动:[
弹出菜单按钮(
键:_键,
itemBuilder:(上下文){
返回[
PopupMenuItem(子项:文本('0'),值:0),
PopupMenuItem(子项:文本('1'),值:1),
];
},
),
],
),
主体:升起按钮(
按下时:()=>\键.currentState.showButtonMenu(),
子项:文本(“打开/关闭菜单”),
),
);
}
}

谢谢Eric!是的,那些github问题中描述的小部件是我一直在寻找的东西。谢谢我使用了这个解决方案使用offset属性来定位它不同的位置如何使用多级PopupMenuItems?我如何将PopUpMenuButton中的onSelected属性使用到您的方法中?比方说,如果value Doge是se选中后,我想导航到Doge.dart页面完美答案,我只需用其他值替换0:
relative.fromLTRB(左,上,左+1,上+1),
  @override
  Widget build(BuildContext context) {

  PopupMenu.context = context;  // This is the set context

    return Scaffold(
      appBar: AppBar(
        title: Text('Show Popup')),
      body: Stack(
        children: <Widget>[
          ListView.builder(
            itemCount: list.length,
            itemBuilder: (context, index) {
             return MaterialButton(
                child: GestureDetector(
                  onTapUp: (TapUpDetails details) {
                    showPopup(details.globalPosition);
                  },
                  child: ListTile(
                    leading: IconButton(
                      icon: Icon(Icons.restaurant_menu),
                    ),
                    title: Text("Select your categories"),
                    subtitle: Text("Sub Title"),
                    // onTap: showPopup,
                  ),
                ),

              );
            },
          ),
        ],
      ),
    );
  }