简体   繁体   English

如何在 showModalBottomSheet 中创建内部导航?

[英]How can I create inner navigation in showModalBottomSheet?

In my app I am trying to implement Badoo-like sort/filter showBottomModalSheet feature.在我的应用程序中,我正在尝试实现类似 Badoo 的排序/过滤 showBottomModalSheet 功能。 I managed to create 2 separate pages, which I can navigate back and forth.我设法创建了 2 个单独的页面,我可以来回导航。 However, the problem I'm facing is the second page in showBottomModalSheet.但是,我面临的问题是 showBottomModalSheet 中的第二页。 Back button works fine until I try to touch outside of the modal, which takes back to the first page.后退按钮工作正常,直到我尝试触摸模式之外,这会返回到第一页。 Instead it should close modal.相反,它应该关闭模式。

User navigates to sort users modal, which shows the 1st page in showBottomModalSheet When user taps "Show gender" it navigates to the second page (the one with different genders).用户导航到排序用户模式,在 showBottomModalSheet 中显示第一页当用户点击“显示性别”时,它导航到第二页(具有不同性别的页面)。 When back button is pressed it navigates to 1st screen until it closes modal completely.当按下后退按钮时,它会导航到第一个屏幕,直到它完全关闭模式。 Touching outside of the modal also closes the modal在模态之外触摸也会关闭模态

The best stackoverflow answer that I tried:我试过的最好的stackoverflow答案:

https://stackoverflow.com/questions/63602999/how-can-i-do-navigator-push-in-a-modal-bottom-sheet-only-not-the-parent-page/63603685#63603685 https://stackoverflow.com/questions/63602999/how-can-i-do-navigator-push-in-a-modal-bottom-sheet-only-not-the-parent-page/63603685#63603685

I also tried using modal_bottom_sheet package, but had no luck.我也尝试使用 modal_bottom_sheet 包,但没有运气。 https://pub.dev/packages/modal_bottom_sheet/example https://pub.dev/packages/modal_bottom_sheet/example

Most of my code behind showBottomModalSheet:我在 showBottomModalSheet 后面的大部分代码:

class Page1 extends StatefulWidget {
  const Page1({
    Key? key
  }) : super(key: key);
  @override
  _Page1State createState() => _Page1State();
}

class _Page1State extends State<Page1> {
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
  int _currentView = 0;
  late List<Widget> pages;

  @override
  void initState() {
    pages = [
      page1(),
      page2(),
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
print("LOG build _currentView ${_currentView}");
    return pages[_currentView];


  }
  Widget page1() {
    return WillPopScope(
        onWillPop: () async {
          return true;
        },
        child: Container(
          decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                  topRight: Radius.circular(60), topLeft: Radius.circular(60))),
          height: 400,
          width: double.maxFinite,
          child: Center(
              child: Column(
            children: [
              Text("First page"),
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    _currentView = 1;
                    print("LOG page1 _currentView ${_currentView}");
                  });
                },
                child: Text("tap to navigate to 2nd page"),
              ),
            ],
          )),
        ));
  }

  Widget page2() {
    return WillPopScope(
        child: Container(
          decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                  topRight: Radius.circular(60), topLeft: Radius.circular(60))),
          height: 400,
          width: double.maxFinite,
      child: Center(
            child: InkWell(
              onTap: () {
                setState(() {
                  _currentView = 0;
                  print("LOG page2 _currentView ${_currentView}");
                });
              },
              child: Text("tap to navigate to 1st screen"),
            ),
          ),
        ),
        onWillPop: () async {
          print("LOG currentView jot $_currentView");
          if (_currentView == 0) {
            return true;
          }

          setState(() {
            _currentView = 0;
          });

          return false;
        });
  }
}

Solution 1解决方案 1

Use a 3rd-party widget to do it, there are a bunch of them.使用 3rd-party 小部件来做到这一点,它们有很多。 Here are some from https://pub.dev/这里有一些来自https://pub.dev/

  1. awesome_select很棒的选择
  2. backdrop_modal_route background_modal_route
  3. bottom_sheet_expandable_bar bottom_sheet_expandable_bar
  4. bottom_sheet bottom_sheet
  5. cupertino_modal_sheet Cupertino_modal_sheet
  6. enter link description here在此处输入链接描述
  7. just_bottom_sheet just_bottom_sheet
  8. sheet床单

Solution 2解决方案 2

Anyway, if you'd like to do it manually I'd do it with Navigator.push / Navigator.pop instead with PageRouteBuilder with barrierDismissible=true .无论如何,如果你想手动完成,我会用Navigator.push / Navigator.pop代替PageRouteBuilderbarrierDismissible=true

It would like the following.它想要以下内容。 Check out the live demo on DartPad .查看DartPad 上的现场演示

截屏

Here's the code:这是代码:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  void _show() async {
    await Navigator.of(context).push(
      PageRouteBuilder(
        opaque: false,
        barrierDismissible: true,
        pageBuilder: (_, __, ___) => const Page1(),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: _show,
        tooltip: 'Settings',
        child: const Icon(Icons.settings),
      ),
    );
  }
}

class Page1 extends StatefulWidget {
  const Page1({Key? key}) : super(key: key);

  @override
  State<Page1> createState() => _Page1State();
}

class _Page1State extends State<Page1> {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Align(
          alignment: Alignment.bottomCenter,
          child: Container(
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: const BorderRadius.only(
                  topRight: Radius.circular(60), topLeft: Radius.circular(60)),
              boxShadow: [
                BoxShadow(
                  color: Colors.grey.withOpacity(0.5),
                  spreadRadius: 5,
                  blurRadius: 7,
                  offset: const Offset(0, 3), // changes position of shadow
                ),
              ],
            ),
            height: 400,
            width: double.maxFinite,
            child: Center(
              child: Material(
                type: MaterialType.transparency,
                child: Column(
                  children: [
                    const Text("First page"),
                    ElevatedButton(
                      onPressed: () async {
                        final backButton =
                            await Navigator.of(context).push<bool?>(
                          PageRouteBuilder(
                            opaque: false,
                            barrierDismissible: true,
                            pageBuilder: (_, __, ___) => const Page2(),
                          ),
                        );

                        if (backButton == null || backButton == false) {
                          if (mounted) Navigator.of(context).pop();
                        }
                      },
                      child: const Text("tap to navigate to 2nd page"),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

class Page2 extends StatelessWidget {
  const Page2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.bottomCenter,
      child: Container(
        decoration: const BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
              topRight: Radius.circular(60), topLeft: Radius.circular(60)),
        ),
        height: 400,
        width: double.maxFinite,
        child: Center(
          child: Material(
            type: MaterialType.transparency,
            child: InkWell(
              onTap: () => Navigator.of(context).pop(true),
              child: const Text("tap to navigate to 1st screen"),
            ),
          ),
        ),
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何创建此UI导航控件? - How can I create this UI navigation control? 如何使用 Jetpack Navigation 创建动态/条件导航? - How can I create dynamic/conditional navigation with Jetpack Navigation? 如何创建一个非静态内部Activity类? - How can I create a non-static inner Activity class? 如何配置 Flutter 的 showModalBottomSheet 打开/关闭动画? - How do I configure Flutter's showModalBottomSheet opening/closing animation? 如何在 Android 上创建此自定义底部导航 - How can I create this custom Bottom Navigation on Android 如何使用浮动菜单选项创建底部导航栏? - How can i create Bottom Navigation Bar with Floating Menu option? 如何创建一个看起来像这样的导航 header 组件? - How can i create a navigation header component looking like that? 如何创建类似于Google Camera应用中使用的抽屉? - How can I create a navigation drawer similar to the one used in the Google Camera app? 如何创建可以在溢出时定位其内部内容的布局 - How to create a layout that can position its inner contents if overflow 如何在Android中将导航栏与导航图一起使用 - how can i use navigation bar with navigation graph in android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM