Flutter:在/替换底部导航栏上显示模态底部表(无障碍)

时间:2021-02-26 10:00:08

标签: flutter

我正在尝试为我自己的 Flutter 应用程序复制一些类似于 Google 地图的功能。同样基于地图,我希望用户能够选择一个兴趣点并可以选择导航到所述位置。

当他们点击“导航”时,我希望底部工作表出现在现有底部导航栏的位置(或顶部),用于基于标签的导航。

showModalBottomSheet() 这样做,但是它有一个障碍,阻止用户与父视图交互。我需要它没有障碍。

showBottomSheet() 没有障碍物,但也没有放置在底部导航栏的顶部。

是否有一些解决方案可以实现此功能?我唯一能想到的就是将底部导航栏添加到一个容器中,该容器将根据用户是否在导航来显示/隐藏,但我觉得这是一个相当黑客的解决方案,并希望有更优雅的东西。

我在下面附上了几张图片:

  • 第一张屏幕截图显示了带有底部导航栏的 iOS 版 Google 地图的标准视图。
  • 第二个屏幕截图显示了“导航前”视图,它是放置在底部导航栏顶部(或代替)底部导航栏的底部工作表。这是我试图复制的观点。

This is the main view with the Bottom Navigation Bar at the bottom

This is the 'pre-navigation' view that shows a bottom sheet without / on top of the Bottom Navigation Bar

2 个答案:

答案 0 :(得分:1)

我找到的解决方案是将包含您的 ScaffoldbottomNavigationBar 小部件包装到另一个 Scaffold 中。我们的想法是在父 Scaffold 内显示您的模态,以便它位于子 bottomNavigationBar 内的 Scaffold 之上。

class _MyWidgetState extends State<MyWidget> {
  bool _showModal = false;
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  PersistentBottomSheetController _bottomSheetController;

  void _showOrHide(bool show) {
    _showModal = show;
    if (_showModal) {
      _bottomSheetController = _scaffoldKey.currentState.showBottomSheet(
        (_) => Container(
          height: MediaQuery.of(context).size.height / 4,
          width: MediaQuery.of(context).size.width,
          child: Text('This is a BottomSheet'),
        ),
        backgroundColor: Colors.white,
      );
    } else {
      if (_bottomSheetController != null) _bottomSheetController.close();
      _bottomSheetController = null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      backgroundColor: Colors.white,
      body: Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'Home',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.business),
              label: 'Business',
            ),
          ],
        ),
        body: Center(
          child: ElevatedButton(
            child: Text('Show/Hide Modal Bottom Sheet'),
            onPressed: () => _showOrHide(!_showModal),
          ),
        ),
      ),
    );
  }
}

在本例中,我通过 ScaffoldState 保留对我的父 _scaffoldKey 的引用,以便我可以在正确的 showBottomSheet 上调用我的 Scaffold

Try the full code on DartPad

截图:

enter image description here enter image description here

答案 1 :(得分:0)

我解决这个问题的方法类似于纪尧姆的回答。将 Scaffold 小部件包装在 Stack 小部件中允许我在底部导航栏顶部放置自定义视图,我只需将其设置为在用户进入“导航模式”时显示。

@override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Scaffold(
          body: CupertinoPageScaffold(
            child: IndexedStack(
              index: _selectedPage,
              children: pageList,
            ),
          ),
          bottomNavigationBar: BottomNavigationBar(
            showSelectedLabels: false,
            showUnselectedLabels: false,
            type: BottomNavigationBarType.fixed,
            items: _tabItems(),
            currentIndex: _selectedPage,
            selectedItemColor: DoralColors.darkBlue,
            onTap: _onTabTapped,
          ),
        ),
        if (_navigating == true)
          _navigationView(destination, destinationAddress),
      ],
    );
  }

在上面的代码中,_navigationView 是我的自定义导航视图。最后我选择不使用任何模态视图,因为我无法让它按照我想要的方式运行。

相关问题