Skip to content

Modal bottom sheets should not dismiss on tapping the sheet body #20720

Closed

Description

@jklint-g

Currently showModalBottomSheet() allows dismissing the displayed sheet by tapping on its body.
The modal bottom sheet should not dismiss upon tapping the general body.

See https://material.io/design/components/sheets-bottom.html#modal-bottom-sheet, modal bottom sheets can only be dismissed by:

  • Tapping a menu item or action within the bottom sheet
  • Tapping the scrim
  • Swiping the sheet down
  • Using a close affordance within the bottom sheet’s top app bar, if available

I can work around this with an opaque noop gesture detector around the sheet widget, but the default behavior ought to conform to material spec.

Activity

  1. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    p: material_uimaterial_ui package in flutter/packages
    on Aug 21, 2018
  2. Narumikun commented on Oct 14, 2018

    @Narumikun

    I'm troubling with the problem too, I wonder how you use the GestureDetector to solve the dismissing of bottom sheet when tapping its body? Could you please show me a simple code example?
    Have already solved, thanks a lot!

  3. jklint-g commented on Oct 15, 2018

    @jklint-g
    Author

    For the record, the fix in our code was to wrap our bottom sheet widget like this. The buttons in the bottom sheet still worked:

    GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: () {},
          child: <existing bottom sheet widget>
    )
    
  4. yathit commented on Nov 18, 2018

    @yathit

    I also agree with this. Model bottom sheet should not closed, because tap does indicate interest in model, not intention to dismiss.

  5. added this to the milestone on Nov 27, 2018
  6. iamhachemi commented on Dec 31, 2018

    @iamhachemi

    I also agree on this, when a user tap on the Model Bottom Sheet, it should not close it.

  7. dominikkallusky commented on Feb 7, 2019

    @dominikkallusky

    This is still happening for me.

  8. leogny commented on Apr 27, 2019

    @leogny

    Agreed. Model sheet should close if tapped outside but not inside unless directed to do so.

  9. Hixie commented on Apr 30, 2019

    @Hixie
    Contributor
  10. marinat commented on May 7, 2019

    @marinat

    Dear developers, let users decide how bottom sheet will react on tap on it's body

  11. self-assigned this
    on May 8, 2019
  12. jaumard commented on May 9, 2019

    @jaumard
    Contributor

    Why just not having this configurable with a dismissable field by default to false to be material compliant?

  13. darrenaustin commented on May 10, 2019

    @darrenaustin
    Contributor

    While this isn't technically a breaking API change, in order to fix this we would be changing the current behavior of the bottom sheet implementation. For those interested I posted a breaking change announcement here:

    https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/flutter-announce/9m39PZCAKkM

    Feel free to add to this ticket to provide feedback.

  14. darrenaustin commented on May 10, 2019

    @darrenaustin
    Contributor

    Why just not having this configurable with a dismissable field by default to false to be material compliant?

    We could add a dismissOnTap boolean field, but that would add complexity to the API for a feature that most apps would never want, and for those that do, it is simple to implement themselves.

  15. dpedrinha commented on Sep 29, 2019

    @dpedrinha

    IMHO anything modal should be dismissed only programatically. When a developer pops anything modal he does it precisely to prevent user interaction with whatever is behind it, so he should have control on how to dismiss it.
    I was trying to use a modalbottomsheet to show some info while performing some async background work and I expected it to force the user to wait for it to finish but he can just tap anywhere on the screen, close the modalbottomsheet and mess with the entire workflow I need (finish loading data before being able to edit it).
    Same goes for modal dialogs. Hardware back button on Android can dismiss it. When instead it should be considered part of the page and pop the entire page, not just the modal.
    But for those who wants to have full control over the modal dismission, you need something like that:

    showModalBottomSheet(
                context: context,
                builder: (BuildContext context) {
                  MyModel model = Provider.of<MyModel>(context); //this is just my model doing the background work. You don't need it
                  return WillPopScope(
                    onWillPop: () async => false, //prevents Android back button and outside tap from popping it
                    child: GestureDetector(
                      behavior: HitTestBehavior.opaque,
                      onTap: () {}, //prevents taps inside the sheet from popping it
                      onVerticalDragStart: (_) {}, //prevents dragging down from popping it
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Row(
                          children: <Widget>[
                            CircularProgressIndicator(),
                            SizedBox(
                              width: 10,
                            ),
                            Text(model.progressText),
                          ],
                        ),
                      ),
                    ),
                  );
                });
    

    showDialog only needs the WillPopScope and barrierDismissible: false, though

    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
    	return WillPopScope(
    	  onWillPop: () async => false,
    	  child: Center(
    		child: CircularProgressIndicator(),
    	  ),
    	);
      },
    );
    

    But honestly? This shouldn't be necessary. This should be the default behavior. All that extra code should be added IF desired, not if undesired. Having to add empty methods to prevent stuff is definitely not the best design and it looks like a real problem in Flutter. My code is full of them just to make things work as expected.

    So here're my suggestions:

    Add: onBackPressed callback for all modals.
    Add: onOutsideTap, onInsideTap and onSwipeDown callbacks (or something like that) to ModalBottomSheet.

    If set, they are enabled. If not set, they are disabled by default. Just like other Widgets on Flutter like FlatButton.

  16. github-actions commented on Aug 15, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  17. locked as resolved and limited conversation to collaborators on Aug 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

frameworkflutter/packages/flutter repository. See also f: labels.p: material_uimaterial_ui package in flutter/packages

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions