Disable drag down to close showModalBottomSheet
Asked Answered
E

4

23

How do I disable / escape drag down gesture within the Bottom Sheet Modal so the user can interact within the modal without accidentally closing the modal?

Updated below with the actual modal bottom sheet.

return showModalBottomSheet(
    context: context,
    builder: (BuildContext context) {
        ...
    }
}
Electrometer answered 18/2, 2019 at 8:58 Comment(0)
P
28

Set enableDrag to false

bool enableDrag

If true, the bottom sheet can dragged up and down and dismissed by swiping downwards.

https://docs.flutter.io/flutter/material/BottomSheet/enableDrag.html

Phono answered 1/3, 2019 at 16:25 Comment(6)
Thanks, I didn't know there was an actual BottomSheet. Unfortunately there is no example of BottomSheet use case "The BottomSheet widget itself is rarely used directly." Is it possible for you to create an example which behaves similar to the Modal showModalBottomSheet version?Electrometer
try something like this. Credits: herePhono
Hmm.. both links do not use BottomSheetElectrometer
Upon additional Google search with enableDrag search term, I was actually unable to find any examples that used that property.Electrometer
It seems the enableDrag property is available in the master channel. not available on the stable yetIronworker
Awesome SolutionAdministrative
E
18

you can try to wrap builder's result with GestureDetector with onVerticalDragStart = (_) {}

showModalBottomSheet(
  context: context,
  builder: (context) => GestureDetector(
    child: **any_widget_here**,
    onVerticalDragStart: (_) {},
  ),
  isDismissible: false,
  isScrollControlled: true,
);
Erinnerinna answered 15/3, 2020 at 11:26 Comment(2)
Thats smart :D It works perfectly for persistent bottom sheet, thank youAmbrogio
easy solution for flutter channel stableGrafton
M
3

If you still want to have the scroll inside the modal without the user drag and close it, you can use this:

                  showModalBottomSheet(
                    context: context,
                    enableDrag: false,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.vertical(
                        top: Radius.circular(20),
                      ),
                    ),
                    clipBehavior: Clip.antiAliasWithSaveLayer,
                    builder: (context) => DraggableScrollableSheet(
                      expand: false,
                      initialChildSize: 0.9,
                      minChildSize: 0.5,
                      maxChildSize: 0.9,
                      builder: (context, scrollController) {
                        return SingleChildScrollView(
                          child: new Container(
                            color: Colors.white,
                            child: buildTitleWidget(),
                          ),
                        );
                      },
                    ),
                    isDismissible: false,
                    isScrollControlled: true,
                  );

The trick is not to add scrollController to the SingleChildScrollView

                      builder: (context, scrollController) {
                        return SingleChildScrollView(
                          controller: scrollController            <-- HERE
                          child: new Container(
                            color: Colors.white,
                            child: buildTitleWidget(),
                          ),
                        );
                      },
Mika answered 21/7, 2021 at 13:50 Comment(0)
O
0

I wanted a bottomsheet that is draggable up and down, but does not close on dragging down. My thought was what if as soon as it closes, I call it again? Here, recursion comes to rescue. So, first of all I created a function for my modalBottomSheet.

Future modalBottomSheetShow(BuildContext context) {
    return showModalBottomSheet(
      backgroundColor: Colors.transparent,
      context: context,
      builder: (context) => buildSheet(),
      isDismissible: false,
      elevation: 0,
    );
  }

Next, I used .whenComplete() method of showModalBottomSheet() to recursively call the modalBottomSheetShow() function.

  Future modalBottomSheetShow(BuildContext context) {
    return showModalBottomSheet(
      backgroundColor: Colors.transparent,
      context: context,
      builder: (context) => buildSheet(),
      isDismissible: false,
      elevation: 0,
    ).whenComplete(() => modalBottomSheetShow(context));
  }

Next, I simply call the modalBottomSheetShow() whenever I wanted a bottomsheet. It cannot be closed, until the recursion ends. Here is the entire code for reference:

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);
  static const idScreen = "HomePage";
  @override
  State<HomePage> createState() => _HomePageState();
}



  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((_) async {
      modalBottomSheetShow(context);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        toolbarHeight: 0,
        elevation: 0,
        backgroundColor: Colors.black,
      ),
    );
  }

  Widget buildSheet() {
    return DraggableScrollableSheet(
      initialChildSize: 0.6,
      builder: (BuildContext context, ScrollController scrollController) {
        return Container(
          decoration: BoxDecoration(color: Colors.white, boxShadow: [
            BoxShadow(
              color: Color(0x6C000000),
              spreadRadius: 5,
              blurRadius: 20,
              offset: Offset(0, 0),
            )
          ]),
          padding: EdgeInsets.all(16),
        );
      },
    );
  }

  Future modalBottomSheetShow(BuildContext context) {
    return showModalBottomSheet(
      backgroundColor: Colors.transparent,
      context: context,
      builder: (context) => buildSheet(),
      isDismissible: false,
      elevation: 0,
    ).whenComplete(() => modalBottomSheetShow(context));
  }
}
Orometer answered 12/1, 2023 at 18:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.