1

In my design, there is a close button in the BottomSheet. I have tried Stack. But it didn't work. Does anyone know how to achieve the result? Thanks :)

Overlap Button in BottomSheet


modalBottomSheet(context) {
  return showModalBottomSheet(
    context: context,
    builder: (context) {
      return Stack(
        children: [
          Container(
            child: Text('Sample Text'),
          ),
          Container(
            height: 50,
            width: 50,
            decoration: BoxDecoration(
              color: Colors.red,
              shape: BoxShape.circle,
            ),
          ),
        ],
      );
    }
  );
}

Jay Tillu
  • 1,348
  • 5
  • 23
  • 40
  • Have you tried using a `floatingActionButton` in the app's scaffold, with different locations? I know this can be used to dock the FAB to the bottom navigation, I'm not sure how it'd react to the bottom sheet, though. Check out the options on here: https://api.flutter.dev/flutter/material/FloatingActionButtonLocation-class.html – fravolt Jun 25 '21 at 12:53
  • The only related question I could find (which you've propbably already taken a look at) proposes using a `Stack` in combination with a `Postioned` widget to make sure they overlap properly. [link to post](https://stackoverflow.com/questions/66368709/flutter-floatingactionbutton-on-modal-bottom-without-scaffold) – fravolt Jun 25 '21 at 12:56
  • Yaa, I have seen it. But `Positioned` and FAB widgets are also not working. – Jay Tillu Jun 25 '21 at 12:59
  • Hi! I was trying around and found a solution. Check it out below :) – fravolt Jun 27 '21 at 22:21

2 Answers2

2

So I've been trying around for a bit, and this seems to work as you explained.

  modalBottomSheet(context) {
    return showModalBottomSheet(
        context: context,
        builder: (context) {
          // using a scaffold helps to more easily position the FAB
          return Scaffold(
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                SizedBox(
                  width: double.maxFinite,
                ),
                Padding(
                  padding: EdgeInsets.all(30.0),
                  child: Text("Text in the sheet"),
                ),
              ],
            ),
            // translate the FAB up by 30
            floatingActionButton: Container(
              transform: Matrix4.translationValues(0.0, -30, 0.0),  // translate up by 30
              child: FloatingActionButton(
                onPressed: () {
                  // do stuff
                  print('doing stuff');
                },
                child: Icon(Icons.add),
              ),
            ),
            // dock it to the center top (from which it is translated)
            floatingActionButtonLocation: FloatingActionButtonLocation.centerTop,
          );
        });
  }

The meat of the solution here is to transform the Container which contains the FAB. I got this idea from this older SO answer to a somewhat related question.

The result looks like this:

screenshot

You'll probably have to make some more edits to achieve the exact result you desire, but I hope this sets you on the right path.

Edit

When, in the above solution, you want to press the FAB, and you tap the top half, the onPressed handler fires, but the modal also closes. You should probably use a WillPopScope that only pops when the actual button is pressed (and not the area around/above it). If you think it's fine pressing anywhere above it as well, you can just leave it as-is.

fravolt
  • 2,565
  • 1
  • 4
  • 19
0
showModalBottomSheet(
          backgroundColor: Colors.transparent,
          context: context,
          builder: (BuildContext context) {
            return Stack(clipBehavior: Clip.none, children: [
              Container(
                decoration: const BoxDecoration(
                    color: Colors.white,
                    borderRadius:
                        BorderRadius.vertical(top: Radius.circular(20))),
                height: 220.h,
                child: Padding(
                  padding: const EdgeInsets.symmetric(
                      horizontal: 10.0, vertical: 16),
                  child: Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                         ElevatedButton(
                            color: Colors.green,
                            onPressed: () {},
                            child: const Center(child: Text('Remove')))
                      ],
                    ),
                  ),
                ),
              ),
              Positioned(
                  top: -30.h,
                  right: 12.w,
                  child: FloatingActionButton(
                    onPressed: () {},
                    child: const Icon(Icons.close),
                  )),
            ]);
          },
        )
  • Welcome to SO! Code only answers are **not considered good answers**, and are likely to be downvoted and/or deleted because they are **less useful** to a community of learners. It's only obvious to you. Explain what it does, and how it's different / **better** than the existing answers. Here are some guidelines for [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) – lepsch Sep 21 '22 at 14:25