How to make Modal Bottom Sheet elevated equally with Bottom App Bar in Flutter?

3,508

A solution would be to have the BottomAppBar in other ascendant Scaffold in your widget tree.

Reduced example:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold( // Your Ascendant Scaffold
        body: MyScreen(),
        bottomNavigationBar: MyBottomAppBar() // Your BottomAppBar here
      ),
    );
  }
}

class MyScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold( // Your descendant Scaffold
      body: Center(
        child: Text('Hello world'),
      ),
    );
  }
}

Complete example:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: MyWidget(),
        bottomNavigationBar: BottomNavigationBar(
          items: [
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'Item 1',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.settings),
              label: 'Item 2',
            ),
          ],
        ),
      ),
    );
  }
}


class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Builder(
          builder: (context) => ElevatedButton(
            child: Text('Show modal bottom sheet'),
            onPressed: () => _displaysBottomSheet(context),
          ),
        ),
      ),
    );
  }

  void _displaysBottomSheet(BuildContext context) {
    Scaffold.of(context).showBottomSheet(
      (context) => Container(
        height: 200,
        color: Colors.amber,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              const Text('BottomSheet'),
              ElevatedButton(
                child: const Text('Close BottomSheet'),
                onPressed: () => Navigator.pop(context),
              )
            ],
          ),
        ),
      ),
    );
  }
}

RESULT ON DEVICE

Share:
3,508
Renaldi Arlin
Author by

Renaldi Arlin

Updated on December 01, 2022

Comments

  • Renaldi Arlin
    Renaldi Arlin over 1 year

    So, I am a new Flutter Developer and currently trying to make my own flutter app without any tutorial. I am confused with the elevation of the Modal Bottom Sheet and Bottom App Bar. I want both of the widgets to be elevated equally. Currently, my app behavior is like this.My App Behaviour. The Bottom Modal Sheet just covers the Bottom App Bar and everything else. My code is something like this.

    home_screen.dart (where my Bottom Modal Sheet, FAB, Bottom App Bar is)

    // Packages
    import 'package:flutter/material.dart';
    import 'package:hive/hive.dart';
    import 'package:hive_flutter/hive_flutter.dart';
    import 'package:moneige/models/transaction.dart';
    
    // UIs
    import '../ui/home_screen/app_bar_title.dart';
    import '../ui/home_screen/bottom_app_bar.dart';
    import '../ui/home_screen/transaction_list_view.dart';
    
    // Widgets
    import '../widget/add_button.dart';
    
    // Styles
    import '../constants/styles.dart' as Styles;
    
    class HomeScreen extends StatelessWidget {
      final int totalBalance = 100000;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          appBar: AppBar(
            backgroundColor: Colors.white,
            title: MyAppBarTitle(totalBalance: totalBalance),
          ),
          body: ValueListenableBuilder(
            valueListenable: Hive.box('transactions').listenable(),
            builder: (context, transactionBox, widget) {
              return (transactionBox.length > 0)
                  ? TransactionListView(transactionBox: transactionBox)
                  : Center(
                      child: Text('You have no transaction yet',
                          style: Styles.textMedium));
            },
          ),
          bottomNavigationBar: MyBottomAppBar(),
          floatingActionButton: AddButton(() {
            Hive.box('transactions').add(Transaction(
                date: DateTime.now(),
                changes: 123000,
                notes: 'Crazier than usual'));
    
            showModalBottomSheet(
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.vertical(top: Radius.circular(25.0)),
                ),
                backgroundColor: Colors.white,
                context: context,
                elevation: 10,
                useRootNavigator: true,
                builder: (BuildContext context) {
                  return Container(height: 200);
                });
          }),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        );
      }
    }
    
    

    bottom_app_bar.dart (where MyBottomAppBar is)

    // Packages
    import 'package:flutter/material.dart';
    import 'package:hive/hive.dart';
    
    // Widgets
    import '../../widget/settings_button.dart';
    import '../../widget/transaction_report_switch.dart';
    
    // Styles
    import '../../constants/styles.dart' as Styles;
    
    class MyBottomAppBar extends StatelessWidget {
      const MyBottomAppBar({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return BottomAppBar(
          shape: CircularNotchedRectangle(),
          color: Styles.colorPrimary,
          child: Row(
            children: [
              Spacer(),
              Container(
                child: TransactionReportSwitch(() => Hive.box('transactions').deleteAll(Hive.box('transactions').keys)),
              ),
              Container(
                child: SettingsButton(),
              ),
            ],
          ),
        );
      }
    }
    

    add_button.dart (where AddButton is)

    // Packages
    import 'package:flutter/material.dart';
    
    // Styles
    import '../constants/styles.dart' as Styles;
    
    class AddButton extends StatelessWidget {
      final Function handler;
    
      AddButton(this.handler);
    
      @override
      Widget build(BuildContext context) {
        return FloatingActionButton(
          child: Icon(
            Icons.add_rounded,
            color: Colors.white,
            size: 28,
          ),
          backgroundColor: Styles.colorPrimary,
          focusColor: Colors.white12,
          hoverColor: Colors.white12,
          foregroundColor: Colors.white12,
          splashColor: Colors.white24,
          onPressed: handler,
        );
      }
    }
    

    I saw a really good animated FAB, Modal Bottom Sheet, and Bottom App Bar composition in the Flutter Gallery app, Reply example. Flutter Gallery Example. (https://play.google.com/store/apps/details?id=io.flutter.demo.gallery&hl=en) When the Modal Bottom Sheet appears, the FAB disappears animatedly and the Sheet and App Bar are equally elevated, also the Sheet is above the Bottom App Bar. This is the behavior I wanted in my app, do you guys have any solution?