19

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) {
        ...
    }
}
Jesse
  • 2,690
  • 9
  • 15
  • 28

4 Answers4

25

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

Community
  • 1
  • 1
Willy
  • 859
  • 8
  • 17
  • 1
    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? – Jesse Mar 06 '19 at 11:19
  • try something like [this](https://gist.github.com/shenwilly/c5ff36e2c3387711cf447528819420e1). Credits: [here](https://stackoverflow.com/questions/51908187/how-to-make-a-full-screen-dialog-in-flutter) – Willy Mar 06 '19 at 15:49
  • Hmm.. both links do not use `BottomSheet` – Jesse Mar 08 '19 at 23:45
  • Upon additional Google search with `enableDrag` search term, I was actually unable to find any examples that used that property. – Jesse Mar 08 '19 at 23:55
  • It seems the enableDrag property is available in the master channel. not available on the stable yet – fvisticot Dec 25 '19 at 11:11
  • Awesome Solution – Fathah Cr Sep 05 '20 at 12:32
14

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,
);
Raj Singh
  • 141
  • 1
  • 6
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(),
                          ),
                        );
                      },
Turbo19973
  • 97
  • 2
  • 9
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));
  }
}
Dhruv Badaya
  • 430
  • 3
  • 15