Samuel Drescher
Samuel Drescher

Reputation: 685

Flutter Showing Snackbar On Top of Bottom Sheet

In my code I call a bottom sheet to display a list of tiles. These tiles contain buttons that display a snackbar. That functionality works fine, the only issue is that the snackbar is displayed behind the bottom sheet so you can only see it if you close the bottom sheet. Each of them are called with the following code:

1. Bottom Sheet:

  void _settingModalBottomSheet(context, stream, scaffoldKey ) {
    if (_availableRides.length == 0) {
      return null;
    } else {
      return scaffoldKey.currentState.showBottomSheet((context) {
        return Column(
          children: Widgets;
      });
    }
  }

2. Snackbar

widget.scaffoldKey.currentState.showSnackBar(SnackBar(
         content: Text("Created", textAlign: 
    TextAlign.center,),),

Does anyone know how I can position the snackbar in front of the bottom sheet

Upvotes: 40

Views: 34374

Answers (10)

Tomas Baran
Tomas Baran

Reputation: 1983

Two conditions have to pass:

1. The bottomSheet (the one that is supposed te be under the snackBar) needs to have a Scaffold widget

2. That Scaffold widget (or SnackBar widget) needs to have a custom key:

Examples:

[Scaffold's key]:

return const Scaffold(
      key: Key('value'),
      body: Placeholder(),
    );

[SnackBar's key]:

ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          key: Key('value'),
          content: Text('Hello Snackbar!'),
        ),
      );

Full example:

import 'package:flutter/material.dart';

void main() {
  runApp(const SunflowerApp());
}

class SunflowerApp extends StatefulWidget {
  const SunflowerApp({super.key});

  @override
  State<StatefulWidget> createState() {
    return _SunflowerAppState();
  }
}

class _SunflowerAppState extends State<SunflowerApp> {
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyScaffold(),
    );
  }
}

class MyScaffold extends StatelessWidget {
  const MyScaffold({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sunflower'),
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Expanded(
              child: Center(
                child: ButtonBar(
                  children: <Widget>[
                    TextButton(
                        child: const Text('Button 1'),
                        onPressed: () => showModalBottomSheet(
                              context: context,
                              builder: (context) => const BasicBottomSheet(),
                            )),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 20),
          ],
        ),
      ),
    );
  }
}

class BasicBottomSheet extends StatelessWidget {
  const BasicBottomSheet({super.key});

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Hello Snackbar!'),
        ),
      );
    });
    return const Scaffold(
      key: Key('value'),
      body: Placeholder(),
    );
  }
}

enter image description here

Upvotes: -1

Muhammed
Muhammed

Reputation: 211

I solved this problem with idle solution but it works

The Solution by 3 steps:

1 Add SizedBox and set the same height of BottomSheet
2 Add Scaffold as child of SizedBox
3 Add Your BottomSheet

SizedBox(
  height: ... ,// height of bottomSheet
  child: Scaffold(
       body: ... , // your bottomSheet
  )
)

Upvotes: 6

Pablo Barrera
Pablo Barrera

Reputation: 10963

SnackBar has a property for this. It's called behavior, you could do this:

SnackBar(
    behavior: SnackBarBehavior.floating,
    ...

SnackBarBehavior enum

floating → const SnackBarBehavior

This behavior will cause SnackBar to be shown above other widgets in the Scaffold. This includes being displayed above a BottomNavigationBar and a FloatingActionButton.

See material.io/design/components/snackbars.html for more details.

Upvotes: 2

I.Step
I.Step

Reputation: 779

This is a working solution according to documentation. https://docs.flutter.dev/cookbook/design/snackbars

This example works with bottom sheets as well.

  1. Initialize ScaffoldMessengerKey.
  2. Wrap your component widget with Scaffold.
  3. Wrap Scaffold with ScaffoldMessenger.
  4. Add key scaffoldMessengerKey to ScaffoldMessenger
  5. Call method scaffoldMessengerKey.currentState?.showSnackBar(SnackBar());

Example:

final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();


// Any widget with button. 
// (Bottom sheet also) - root widget must be ScaffoldMessenger.
ScaffoldMessenger(
  key: scaffoldMessengerKey,
  child: Scaffold(
    body: Container(
      child: ElevatedButton(
        style: raisedButtonStyle,
        onPressed: () { 
          scaffoldMessengerKey.currentState?.showSnackBar(
            //SnackBar design.
            SnackBar(
             backgroundColor: Colors.white,
             elevation: 8,
             content: Container(
               decoration: BoxDecoration(
                 color: Colors.white,
                 borderRadius: BorderRadius.circular(5),
               ),
               child: Text(
                 'Simple snackbar text.',
                 style: FlutterFlowTheme.of(context).bodyText1
                 .override(fontFamily: 'Rubik',
                          fontWeight: FontWeight.w300,
                          lineHeight: 1.5,
               ),
             ),
             action: SnackBarAction(
                label: 'Undo',
                onPressed: () {
                  // Some code to undo the change.
                },
             ),
             duration: Duration(seconds: 5),
             behavior: SnackBarBehavior.floating,
               
       },
       child: Text('Open snackbar over bottom sheet!'),
      ); //ElevatedButton
    ); //Container
  ); //Scaffold
); //ScaffoldMessenger

Note: With this approach you don't need to pass BuildContext.

If you don't want to register ScaffoldMessengerKey. You can show SnackBar like this: ScaffoldMessenger.of(context).showSnackBar(SnackBar());

Upvotes: 0

&#194;ngelo Savioti
&#194;ngelo Savioti

Reputation: 49

I arrived on pretty decent solution. I wrapped my bottom sheet in a Scaffold, but I added it as the bottomSheet parameter. While adding the Scaffold, some trailing background will be added, so I just made its background transparent.

Scaffold(
  backgroundColor: Colors.transparent,
  bottomSheet: ...,
)

Upvotes: 3

BIS Tech
BIS Tech

Reputation: 19514

you can use flushbar package. I think this is the better option if need to use with bottomSheet.

context should be your page's context, not bottomsheet context

any event inside bottomSheet

 CustomFlushBar().flushBar(text: 'Thank you for your payment!', context: context,duration: 2);

CustomFlushBar class

  class CustomFlushBar {
      void flushBar({int duration, @required String text, Color iconColor, IconData iconData, Color backgroundColor, @required BuildContext context}) async {
        await dismiss();
        Flushbar(
          margin: EdgeInsets.all(8),
          borderRadius: 8,
          backgroundColor: backgroundColor ?? Palette.greenButton,
          icon: Icon(iconData ?? Icons.done, color: iconColor ?? Palette.white),
          flushbarStyle: FlushbarStyle.FLOATING,
          message: text,
          duration: Duration(seconds: duration ?? 3),
        )..show(context);
      }
    
      Future<void> dismiss() async {
        if (!Flushbar().isDismissed()) {
          await Flushbar().dismiss();
        }
      }
    }

Upvotes: -1

You can achieve this Simply by wrapping your BottomSheet widget with a Scaffold.

eg:

 void _settingModalBottomSheet(context, stream, scaffoldKey ) {
    if (_availableRides.length == 0) {
      return null;
    } else {
      return scaffoldKey.currentState.showBottomSheet((context) {
        return Scaffold(
           body: Column(
             children: Widgets;
           })
         );
    }
  }

Upvotes: 3

Esmaeil Ahmadipour
Esmaeil Ahmadipour

Reputation: 1192

I solved by Set (padding from bottom to SnackBar) As much as the height of the (bottomSheet : height) .

In This Case I Have This bottomSheet:

bottomSheet: Container(
          child: RaisedButton(...),
          width: MediaQuery.of(context).size.width,
          height: AppBar().preferredSize.height * 0.85,
        ),

And This snackBar:

_scaffoldKey.currentState.showSnackBar(SnackBar(
padding:EdgeInsetsDirectional.only(
bottom:AppBar().preferredSize.height * 0.85),
backgroundColor: Colors.red,
duration: new Duration(milliseconds: 3000),
content: Text('ETC..'),
                ));

Upvotes: 1

Lee Mordell
Lee Mordell

Reputation: 641

I solved this by changing bottomSheet to bottomNavigationBar since the floating snack bar solution didn't work for me.

Upvotes: -1

Samuel Drescher
Samuel Drescher

Reputation: 685

So I was able to solve this by just adding another Scaffold() to my Bottom sheet and passing it a new scaffold key

Upvotes: 23

Related Questions