12

I want my bottom sheet to stay on the screen till I close it from a code. Normally the bottom sheet can be closed by pressing back button(device or appbar) or even just by a downward gesture. How can I disable that?

_scaffoldKey.currentState
        .showBottomSheet<Null>((BuildContext context) {
      final ThemeData themeData = Theme.of(context);
      return new ControlBottom(
        songName: songName,
        url: url,
        play: play,
        pause: pause,
        state: test,
        themeData: themeData,
      );
    }).closed.whenComplete((){

    });

Control botton is a different widget.

Ayush Singh
  • 1,409
  • 3
  • 19
  • 31

5 Answers5

23

Scaffold now has a bottom sheet argument and this bottom sheet cannot be dismissed by swiping down the screen.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(....),
        bottomSheet: Container(
            child: Text('Hello World'),
        ),
    );
  }
nico
  • 63
  • 1
  • 1
  • 6
Ayush Singh
  • 1,409
  • 3
  • 19
  • 31
  • This is not working for me , Please help me with examples – Savad Sep 30 '19 at 13:01
  • 1
    When you specify the bottom sheet using Scaffold's bottomSheet property, then rounded corners won't work (maybe there is some way, but after 1h of searching, I'm going back to my previous Stack-based bottom sheet implementation). – Bartek Pacia Jul 08 '21 at 23:08
3

Also you can use WillPopScope Widget to control pressing back button:

Widget _buildBottomSheet() {
    return WillPopScope(
        onWillPop: () {
            **here you can handle back button pressing. Just leave it empty to disable back button**
        },
        child: **your bottom sheet**
        )),
    );
}
cfnerd
  • 3,658
  • 12
  • 32
  • 44
  • 1
    Thanks, this actually prevents back button from executing on modal sheet, is there a way to force the back button to work on the navigation stack that was there before bottom sheet was opened. – skjagini Jan 23 '19 at 00:48
  • @skjagini did you find any solution for this? – Zubair Rehman Oct 02 '19 at 10:52
1

You can remove the appbar back button by providing an empty container in leading property.

AppBar(
  leading: Container(),
);

But we don't have any control over device back button & bottomsheet will disappear on back pressed.
One of the many alternative approach could be using a stack with positioned & opacity widget

Example :

Stack(
  children: <Widget>[
  // your code here
    Positioned(
      left: 0.0,
      right: 0.0,
      bottom: 0.0,
      child: Opacity(
        opacity: _opacityLevel,
        child: Card(
          child: //Your Code Here,
        ),
      ),
    ),
  // your code here
  ],
);

You can change _opacityLevel from 0.0 to 1.0 when a song is selected.

From what I can make out from your code is that you will be having a listView on top & music controls on the bottom. Make sure to add some Padding at the end of listView so that your last list item does not stay hidden behind your music controller card when you have scrolled all the way down.

If you want to further customize the look & feel of your music controller. You could use animationController or sizeAnimation to slide it from the bottom like a bottomSheet.

I hope this helps.

Ashutosh
  • 821
  • 7
  • 11
0

Add this parameters to showmodalbottomsheet, isDismissible: false, enableDrag: false,

0

I wanted a bottomsheet that is draggable up and down, but does not close. 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