【问题标题】:Close modal bottom sheet programmatically in flutter在颤动中以编程方式关闭模态底部表
【发布时间】:2018-09-21 13:30:24
【问题描述】:

我正在通过showModalBottomSheet<Null>() 和几个带有 GestureDetector 的小部件显示一个 BottomSheet。 我希望看到 BottomSheet 不仅通过触摸它的外部而且在内部的 GestureDetector 的 onTap 事件之后关闭。但是,GestureDetector 似乎没有转发触摸事件。

所以我想知道,有没有办法以编程方式触发 ModalBottomSheet 的关闭,或者告诉 GestureDetector 转发触摸事件?

更新(2018-04-12):

以下代码 sn-p 以便更好地理解。问题是当点击“Item 1”或“Item 2”时,ModalBottomSheet 没有关闭。

showModalBottomSheet<Null>(context: context, builder: (BuildContext context)
{
  return new SingleChildScrollView(child:
    new Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
      new GestureDetector(onTap: () { doSomething(); }, child:
        new Text("Item 1")
      ),
      new GestureDetector(onTap: () { doSomething(); }, child:
        new Text("Item 2")
      ),
    ]),
  );
});

【问题讨论】:

  • “内外”这太不清楚了,您可能需要包含插图或显示相关代码

标签: dart flutter


【解决方案1】:

以编程方式关闭 ModalBottomSheet 是通过

Navigator.pop(context);

所以我只是在 GestureDetector 的 onTap 回调函数中调用 pop 函数。

showModalBottomSheet(context: context, builder: (BuildContext context)
{
  return SingleChildScrollView(child:
    Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
      GestureDetector(onTap: () {
          Navigator.pop(context);
          doSomething();
        }, child:
        Text("Item 1")
      ),
      GestureDetector(onTap: () {
          Navigator.pop(context);
          doSomething();
        }, child:
        Text("Item 2")
      ),
    ]),
  );
});

【讨论】:

  • 太棒了!由于 doSomething 方法也可以使用 Navigator 并打开新页面,因此最好在调用“doSomething()”之前调用“Navigator.pop(context)”。
【解决方案2】:

简答:

使用以下任何一种:

Navigator.pop(context);
Navigator.of(context).pop();

长答案:

一般有两种底片。

  1. showModalBottomSheet => 类似于Dialog,而不是Scaffold 的一部分

  2. showBottomSheet => Scaffold 的一部分,这是持久的。


1。显示和隐藏showModalBottomSheet

此代码显示底部表格,并在点击 FlutterLogo 时隐藏它

@override
void initState() {
  super.initState();
  Future(() {
    showModalBottomSheet(
      context: context,
      builder: (_) {
        return GestureDetector(
          onTap: () => Navigator.of(context).pop(), // Closing the sheet.
          child: FlutterLogo(size: 200),
        );
      },
    );
  });
}

输出:


2。显示和隐藏showBottomSheet

这段代码显示了一个按钮,它将打开和关闭底部的工作表。

late PersistentBottomSheetController _controller;
GlobalKey<ScaffoldState> _key = GlobalKey();
bool _open = false;
  
@override
Widget build(BuildContext context) {
  return Scaffold(
    key: _key,
    body: Center(
      child: ElevatedButton(
        onPressed: () {
          if (!_open) {
            _controller = _key.currentState!.showBottomSheet(
              (_) => SizedBox(
                child: FlutterLogo(size: 200),
                width: double.maxFinite,
              ),
            );
          } else {
            _controller.close();
          }
          setState(() => _open = !_open);
        },
        child: Text(_open ? "Close" : "Open"),
      ),
    ),
  );
}

输出:

【讨论】:

  • 迟到了,但在第二个例子中,你需要GlobalKey 做什么?
  • @JJuice 您需要GlobalKey 才能获得ScaffoldState。另一种方法是使用BuilderScaffold.of(context).showBottomSheet(...)
【解决方案3】:
class _FABState extends State<FAB> {
  bool isOpen = false;

  var bottomSheetController;

  @override
  Widget build(BuildContext context) {
    return FloatingActionButton(
      onPressed: () {
        setState(() {
          isOpen = !isOpen;
        });
        print('tapped on the bottom sheet');
        if(isOpen) {
          bottomSheetController = showBottomSheet(
              backgroundColor: Colors.transparent,
              context: context,
              builder: (ctx) {
                return ClipRRect(
                  borderRadius: BorderRadius.only(
                    topRight: Radius.circular(20),
                    topLeft: Radius.circular(20),
                  ),
                  child: Container(
                    height: 150,
                    color: Colors.black,
                    child: TextField()
                  ),
                );
              });
          bottomSheetController.closed.then((value) {
            setState(() {
              isOpen = !isOpen;
            });
          });
        } else {
          Navigator.of(context).pop();
          setState(() {
            isOpen = !isOpen;
          });
        }
      },
      child: isOpen?Icon(Icons.arrow_downward):Icon(Icons.arrow_upward),
    );
  }
}

【讨论】:

    【解决方案4】:

    我们代码中的修复是像这样包装我们的底部工作表小部件。底部表格中的按钮仍然有效:

    GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: () =>  Navigator.pop(context),
          child: <existing bottom sheet widget>
    )
    

    【讨论】:

      【解决方案5】:

      在颤动中显示和隐藏底部工作表:

       showModalBottomSheet(
          context: context,
          builder: (bCtx) {
            return GestureDetector(
              behavior: HitTestBehavior.opaque,
              child: Container(height: 300, child: Text('Bottom sheet widget'),),
              onTap: () {
                Navigator.of(context).pop();
              },
            );
          },
        );
      

      【讨论】:

        【解决方案6】:

        如果您的模态表没有下降并直接返回上一页,那么您可以使用{useRootNavigator:true},然后使用另一个函数中的Navigator.pop(context);。它只会隐藏模式表,而不是转到上一页。

        【讨论】:

          【解决方案7】:

          如果您使用带有脚手架键和持久底部表控制器的底部表,我的方式是这样的;

          final scaffoldState = GlobalKey<ScaffoldState>();
          dynamic controller;
                  
          if(controller!=null){
             controller as PersistentBottomSheetController).close();
             controller=null;
          }
              
          override
          void dispose() {
             if(controller!=null){
                controller as PersistentBottomSheetController).close();
             }
             super.dispose();
          }
          
          

          这样,就像我的小部件层次结构一样;如果用户点击底部导航栏,用户可以更改当前页面,我正在关闭当前底部页面。

          如果用户自己关闭底部表格,对于我们的动态控制器,我们可以关闭控制器并将其分配为空值。这样,我们就可以知道底部工作表是否存在。

          【讨论】:

            猜你喜欢
            • 2020-10-26
            • 2022-08-12
            • 1970-01-01
            • 2010-10-31
            • 2020-04-23
            • 2021-01-14
            • 2016-01-30
            • 1970-01-01
            • 2015-10-20
            相关资源
            最近更新 更多