Flutter - показывает PopupMenuButton в BottomNavigationBar - PullRequest
0 голосов
/ 16 ноября 2018

Я пытаюсь показать меню при нажатии на элемент панели навигации.Это была моя попытка:

  @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.Между icon и title есть отступ, который я не смог удалить (даже добавив padding: EdgeInsets.all(0.0)) (как показано на рисунке ниже).И второе: мне нужно точно щелкнуть значок, чтобы появилось меню.enter image description here enter image description here

Я пытался вызвать showMenu напрямую (метод, который вызывает PopupMenuButton), когда BottomNavigationBarItem из index=2 (например) нажата.Но было непросто определить место происхождения, откуда должно появиться меню.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Вот попытка, которая использует 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()));
  }
0 голосов
/ 16 ноября 2018

Вот моя попытка:

@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, чтобы они были в правом нижнем углулюбого устройства.Вы можете возиться с этими значениями, чтобы получить позицию более прямо над значком, но я думаю, что это хорошо работает:

enter image description here

...