【问题标题】:How to pass data back from modal in flutter?如何在颤动中从模态传回数据?
【发布时间】:2022-01-02 21:04:01
【问题描述】:

所以基本上我使用showModalBottomSheet 小部件来显示一个全屏容器,该容器有一个运行此onTap 的GestureDetector

onTap: () {
  final String testText = "Sup";
  Navigator.of(context).pop(testText);
}

这显然在我await 时返回文本当我调用showModalBottomSheet 时返回结果但是,我还想设置enableDrag: true 以便我们可以将模态滑开。

我的问题是:

如何在滑动关闭时将参数/结果传回?使用函数,我可以简单地做Navigator.of(context).pop(...),但是当我们滑动时,没有函数,因此当我们滑动关闭时我无法找到传递参数的方法。

谢谢!

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    当您滑动时,pop() 方法被调用并且无论如何都无法覆盖它,但我想出了一种处理这种情况的方法:

    您可以像这样在 showModalBottomSheet() 上使用 then() 方法:

    showModalBottomSheet(context: context, builder: (context) => SecondPage()).then((value) {
            str = "done";
            print("data: $str");
          });
    

    请记住,future 返回的值是 pop() 方法中返回的值,否则为 null。

    【讨论】:

    • 这不是只有在我们要返回的数据是常量的情况下才有效吗?我要返回的数据是动态的,它的值是由modal中的小部件决定的。
    【解决方案2】:

    看起来showModalBottomSheet 没有办法指定收盘价。所以在这种情况下它总是返回null。而且您无能为力。但我看到的选项:

    • 使用结果包装器通过引用返回值。像这样:
    class MyResult {
        int myValue;
    }
    
    class MyBottomWidget ... {
        MyResult result;
        MyBottomWidget(this.result);
    
        // then you can initialize the value somewhere
        // result.myValue = 5;
    }
    
    final result = MyResult();
    await showModalBottomSheet(context: context, builder: (_) => MyBottomWidget(result);
    // and here you can use your value
    print('Result value: ${result.myValue});
    
    
    • 另一种方法是,如果showModalBottomSheet 的结果是null,则返回一个值,这意味着模式已关闭/解除。
    
    final result = await showModalBottomSheet(...);
    if (result == null) {
        // initialize the value with a value you need when modal is closed.
    }
    

    你可以制作一个 func 包装器来简化这个过程:

    Future<T> myShowModalBottomSheet<T>(BuildContext context, WidgetBuilder builder, T dismissValue) async {
      final value = await showModalBottomSheet<T>(context: context, builder: builder);
      return value ?? dismissValue;
    }
    

    或类似:

    Future<T> myShowModalBottomSheet<T>(BuildContext context, WidgetBuilder builder, T Function() dismissedValueBuilder) async {
      final value = await showModalBottomSheet<T>(context: context, builder: builder);
      return value ?? dismissedValueBuilder();
    }
    
    • 另一种方法是创建自己的shoModalBottomSheet,这将允许指定值。该函数的源代码是可用的,因此实现它并不难。这将是最干净的解决方案,但它也有一些缺点。首先是要做的事情更多。另一件事是您的解决方案将与本机颤振功能不同步。 IE。如果颤动会改变该函数或小部件的行为,您将需要更新您的代码。
    • pub.dev 上搜索具有您需要的功能的软件包。

    也许还有其他方法,但我不知道)。

    【讨论】:

      【解决方案3】:

      使用此小部件并添加导航器。流行音乐。

      ->使用这个 WillPopScope

      欲了解更多信息,请访问Click Here

      如果你想在pop中传递数据。然后看例子:-

      import 'package:flutter/material.dart';
      
      void main() {
        runApp(
          const MaterialApp(
            title: 'Returning Data',
            home: HomeScreen(),
          ),
        );
      }
      
      class HomeScreen extends StatelessWidget {
        const HomeScreen({Key? key}) : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: const Text('Returning Data Demo'),
            ),
            body: const Center(
              child: SelectionButton(),
            ),
          );
        }
      }
      
      class SelectionButton extends StatelessWidget {
        const SelectionButton({Key? key}) : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return ElevatedButton(
            onPressed: () {
              _navigateAndDisplaySelection(context);
            },
            child: const Text('Pick an option, any option!'),
          );
        }
      
        // A method that launches the SelectionScreen and awaits the result from
        // Navigator.pop.
        void _navigateAndDisplaySelection(BuildContext context) async {
          // Navigator.push returns a Future that completes after calling
          // Navigator.pop on the Selection Screen.
          final result = await Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const SelectionScreen()),
          );
      
          // After the Selection Screen returns a result, hide any previous snackbars
          // and show the new result.
          ScaffoldMessenger.of(context)
            ..removeCurrentSnackBar()
            ..showSnackBar(SnackBar(content: Text('$result')));
        }
      }
      
      class SelectionScreen extends StatelessWidget {
        const SelectionScreen({Key? key}) : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: const Text('Pick an option'),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: ElevatedButton(
                      onPressed: () {
                        // Close the screen and return "Yep!" as the result.
                        Navigator.pop(context, 'Yep!');
                      },
                      child: const Text('Yep!'),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: ElevatedButton(
                      onPressed: () {
                        // Close the screen and return "Nope." as the result.
                        Navigator.pop(context, 'Nope.');
                      },
                      child: const Text('Nope.'),
                    ),
                  )
                ],
              ),
            ),
          );
        }
      }
      

      选择屏幕:-

      Navigator.pop(context, 'Yep!');
      

      按钮代码(像这样的导航器推送):-

       final result = await Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const SelectionScreen()),
      

      For More Information

      【讨论】:

      • 我检查了它,但它没有帮助,因为它仅在您显式调用 pop() 并按下 appbar 后退按钮时才有用
      • 检查这个更新的答案。
      猜你喜欢
      • 2019-01-21
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 1970-01-01
      • 1970-01-01
      • 2017-04-21
      • 2022-06-10
      相关资源
      最近更新 更多