【问题标题】:Flutter - showing a PopupMenuButton in BottomNavigationBarFlutter - 在 BottomNavigationBar 中显示一个 PopupMenuButton
【发布时间】:2018-11-16 12:01:25
【问题描述】:

我试图在单击导航栏项目时显示菜单。这是我的尝试:

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
        length: 3,
        child: Scaffold(
            appBar: MyAppBar(
              title: "Home",
              context: context,
            ),
            bottomNavigationBar: BottomNavigationBar(
              items: [
                BottomNavigationBarItem(
                    icon: new Icon(Icons.home), title: Text('Home')),
                BottomNavigationBarItem(
                    icon: new Icon(Icons.book), title: Text('Second')),
                BottomNavigationBarItem(
                    icon: new PopupMenuButton(
                      icon: Icon(Icons.add),
                      itemBuilder: (_) => <PopupMenuItem<String>>[
                            new PopupMenuItem<String>(
                                child: const Text('test1'), value: 'test1'),
                            new PopupMenuItem<String>(
                                child: const Text('test2'), value: 'test2'),
                          ],
                    ),
                    title: Text('more')),
              ],
              currentIndex: 0,
            ),
            body: new Container()));
  }

我遇到了两个问题。第一个是 NavigationBarItem 的显示。 icontitle 之间有一个我无法删除的填充(即使添加 padding: EdgeInsets.all(0.0))(如下图所示)。第二个是我需要准确地单击图标才能显示菜单。

当单击index=2(例如)的BottomNavigationBarItem 时,我尝试直接调用showMenuPopupMenuButton 调用的方法)。但是如何确定菜单应该从哪里出现是很棘手的。

【问题讨论】:

    标签: dart flutter flutter-layout


    【解决方案1】:

    这里尝试直接使用showMenu 并调用函数buttonMenuPosition 来获取菜单的位置。它相当脆弱,但您可以将按钮的位置更改为中间,例如使用bar.size.center 而不是bar.size.bottomRight。使用一些 MATH 并通过手动操作 Offset 对象(如果/当您有超过 3 个项目时),您可以更改位置以将菜单放在一个不是中心或在结束)。

    RelativeRect buttonMenuPosition(BuildContext c) {
        final RenderBox bar = c.findRenderObject();
        final RenderBox overlay = Overlay.of(c).context.findRenderObject();
        final RelativeRect position = RelativeRect.fromRect(
          Rect.fromPoints(
            bar.localToGlobal(bar.size.bottomRight(Offset.zero), ancestor: overlay),
            bar.localToGlobal(bar.size.bottomRight(Offset.zero), ancestor: overlay),
          ),
          Offset.zero & overlay.size,
        );
        return position;
      }
    
    
      @override
      Widget build(BuildContext context) {
    
        final key = GlobalKey<State<BottomNavigationBar>>();
    
        return DefaultTabController(
            length: 3,
            child: Scaffold(
                appBar: AppBar(
                  title: Text("Home"),
                ),
                bottomNavigationBar: BottomNavigationBar(
                  key: key,
                  items: [
                    const BottomNavigationBarItem(
                        icon: Icon(Icons.home), title: Text('Home')),
                    const BottomNavigationBarItem(
                        icon: Icon(Icons.book), title: Text('Second')),
                    const BottomNavigationBarItem(
                        icon: Icon(Icons.add), title: Text('more')),
                  ],
                  currentIndex: 0,
                  onTap: (index) async {
                    final position = buttonMenuPosition(key.currentContext);
                    if (index == 2) {
                      final result = await showMenu(
                        context: context,
                        position: position,
                        items: <PopupMenuItem<String>>[
                          const PopupMenuItem<String>(
                              child: Text('test1'), value: 'test1'),
                          const PopupMenuItem<String>(
                              child: Text('test2'), value: 'test2'),
                        ],
                      );
                    }
                  },
                ),
                body: Container()));
      }
    

    【讨论】:

    • 这个答案值得更多的支持!!如何定位 showMenu 小部件在官方文档中并不清楚,尤其是当您必须相对于另一个小部件定位它时。
    【解决方案2】:

    这是我的尝试:

    @override
      Widget build(BuildContext context) {
        return Material(
            child:  DefaultTabController(
            length: 3,
            child: Scaffold(
                appBar: AppBar(
                  title: Text("Home"),
                ),
                bottomNavigationBar: BottomNavigationBar(
                  items: [
                    BottomNavigationBarItem(
                        icon: new Icon(Icons.home), title: Text('Home')),
                    BottomNavigationBarItem(
                        icon: new Icon(Icons.book), title: Text('Second')),
                    BottomNavigationBarItem(
                        icon: new Icon(Icons.add),
                        title: Text('More')),
                  ],
                  currentIndex: 0,
                  onTap: (int index) async {
                    if(index == 2){
                      await showMenu<String>(
                        context: context,
                        position: RelativeRect.fromLTRB(1000.0, 1000.0, 0.0, 0.0),
                        items: <PopupMenuItem<String>>[
                          new PopupMenuItem<String>(
                                    child: const Text('test1'), value: 'test1'),
                                new PopupMenuItem<String>(
                                    child: const Text('test2'), value: 'test2'),
                        ],
                        elevation: 8.0,
                      );
                    }
                  },
                ),
                body: new Container())));
      }
    

    基本上使用您所说的showMenu 方法,只是我将RelativeRect 的值设置为1000.0,以便它位于任何设备的右下角。您可以使用这些值来获得更正确的图标上方的位置,但我认为这样的效果很好:

    【讨论】:

    • 这是对 rect 值的硬编码,对于其他设备来说不是“可扩展的”,是吗?
    • 我更喜欢使用Size _size = MediaQuery.of(context).size;,然后将左侧和顶部值的宽度设置为_size.width,将高度设置为_size.height
    猜你喜欢
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多