【问题标题】:Flutter: Show Modal Bottom Sheet over/replacing Bottom Navigation Bar (without barrier)颤振:在/替换底部导航栏上显示模态底部表(无障碍)
【发布时间】:2021-05-28 16:58:04
【问题描述】:

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

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

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

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

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

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

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

【问题讨论】:

  • 你找到什么好的解决方案了吗?我有同样的问题:D
  • 我最终做了类似于 Guillaume 在下面回答的事情。我将包含 BottomNavigationBar 的 Scaffold 包装到 Stack 小部件中,然后在其顶部添加我的自定义导航视图,并将其设置为在用户进入“导航模式”时显示。我已经在下面为您发布了我的代码。 stackoverflow.com/a/68208539/1280479

标签: flutter


【解决方案1】:

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

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),
          ),
        ),
      ),
    );
  }
}

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

Try the full code on DartPad

截图:

【讨论】:

    【解决方案2】:

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

    @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 是我的自定义导航视图。我最终选择不使用任何模态视图,因为我无法让它发挥我想要的作用。

    【讨论】:

      【解决方案3】:

      使用 useRootNavigator: true from showBottomModalSheet

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 2022-09-22
      • 2017-10-27
      • 2021-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 2022-01-03
      相关资源
      最近更新 更多