Skip to content

Scaffold BottomSheet Does Not Respect Elevation Property When Using BottomNavigationBar with Elevation #43251

Open
@workerbee22

Description

@workerbee22

Create a BottomSheet for a Scaffold and show it using showBottomSheet. BottomSheet has an elevation property but his is not respected.

If the Scaffold includes a BottomNavigationBar (which also has an elevation property) then when the BottomSheet is opened, it animates from the bottom of the screen (ie. bottom of the Scaffold) always over the top of the BottomNavigationBar.

Despite BottomSheet having an elevation lower eg. 3, than the elevation of the BottomNavigationBar eg. 10, the BottomSheet always animated OVER the BottomNavigationBar.

Expected behaviour: If elevation of BottomSheet is lower than the BottomNavigationBar elevation, then the opening of the BottomSheet animates BEHIND the BottomNavigationBar.

flutter doctor -v
[✓] Flutter (Channel stable, v1.9.1+hotfix.5, on Mac OS X 10.14.6 18G103, locale en-AU)
    • Flutter version 1.9.1+hotfix.5 at /Users/gamma/Documents/flutter
    • Framework revision 1aedbb1835 (5 days ago), 2019-10-17 08:37:27 -0700
    • Engine revision b863200c37
    • Dart version 2.5.0

 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at /Users/gamma/Library/Android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • ANDROID_HOME = /Users/gamma/Library/Android/sdk
    • Java binary at: /Applications/Android Studio 3.5 Preview.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.1, Build version 11A1027
    • CocoaPods version 1.7.5

[✓] Android Studio (version 3.5)
    • Android Studio at /Applications/Android Studio 3.5 Preview.app/Contents
    • Flutter plugin version 40.2.2
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] VS Code (version 1.39.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.5.1

[✓] Connected device (1 available)
    • Nexus 6P • CVH7N15A17000241 • android-arm64 • Android 8.1.0 (API 27)

• No issues found!
Full example code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter BottomSheet',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter NEW BottomSheet Presistent'),
    );
  }
}

// Article example Home was stateless, but I think I want stateful for now
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  // Index of the current bottom nav bar items, defaults to the second item
  int _currentIndex = 1;

  static const infoAppIcon = Icon(
    Icons.info,
    color: Colors.white,
  );

  // Bottom nav bar items lists in the other screen files
  final List<Widget> _children = [
    Container(color: Colors.red),
    Container(color: Colors.blue),
    Container(color: Colors.green),
  ];

  // This function takes in the BottomNavBarItem's tab index and calls setState on our state class
  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        // To stop back button showing as leading icon when bottom sheet is showing
        automaticallyImplyLeading: false,
      ),
//      body: Center(
//        child: Column(
//          mainAxisAlignment: MainAxisAlignment.center,
//          children: <Widget>[
//            Text(
//              'Main page with Scaffold content',
//            ),
//          ],
//        ),
//      ),
      body: _children[_currentIndex],
      //backgroundColor: Styles.appBgColor,
      bottomNavigationBar: BottomNavigationBar(
        elevation: 5.0,
        onTap: onTabTapped,
        currentIndex: _currentIndex,
        type: BottomNavigationBarType.fixed,
        // TODO Hard coded for now, but can use the canvas color, see doco
        // If type is fixed, then does NOT use BottomNavigationBarItem.backgroundColor like if type shifting
        backgroundColor: Colors.green,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: infoAppIcon,
            title: Text(
              "Screen 1",
              //style: Styles.bottomNavButtonTextStyle,
            ),
            backgroundColor: Colors.blueGrey,
          ),
          BottomNavigationBarItem(
            icon: infoAppIcon,
            title: Text(
              "Screen 2",
              //style: Styles.bottomNavButtonTextStyle,
            ),
            backgroundColor: Colors.blueGrey,
          ),
          BottomNavigationBarItem(
            icon: infoAppIcon,
            title: Text(
              "Screen 3",
              //style: Styles.bottomNavButtonTextStyle,
            ),
            backgroundColor: Colors.blueGrey,
          ),
        ],
      ),
      floatingActionButton: MyFloatingActionButton(),
    );
  }
}

class MyFloatingActionButton extends StatefulWidget {
  @override
  _MyFloatingActionButtonState createState() => _MyFloatingActionButtonState();
}

class _MyFloatingActionButtonState extends State<MyFloatingActionButton> {

  bool showFab = true;
  PersistentBottomSheetController bottomSheetController;   // define it first, will be assigned once bottomSheet created

  void showFloatingActionButton(bool value) {
    setState(() {
      showFab = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    // return FAB is showFAb state is true, otherwise Container
    return (showFab) ? FloatingActionButton(
      onPressed: () {
        // BottomSheet Opens
        // NEW Use showBottomSheet method inside onPressed
        // returns a bottomsheet controller when called
        bottomSheetController = showBottomSheet(
          context: context,
          //elevation: 7.0,   // use white background to see bigger elevation shadow
          backgroundColor: Colors.white,
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(15),
                topRight: Radius.circular(15),
              ),
          ),
          // Use a builder
          builder: (context) => Container(
            //color: Colors.blueGrey,
            height: 200,
            child: Padding(
              padding: const EdgeInsets.all(12.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Row(
                    mainAxisSize: MainAxisSize.max,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text(
                        'Filters',
                        style:
                        TextStyle(color: Colors.black, fontFamily: 'ProductSans'),
                      ),
                      Spacer(),
                      IconButton(
                        icon: Icon(Icons.keyboard_arrow_down, color: Colors.black26),
                        onPressed: () {
                          // Can close bottom sheet a couple of ways
                          //Navigator.of(context).pop();
                          bottomSheetController.close();
                        },
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ));

        // If bottom sheet is open then do not show FAB, via state
        showFloatingActionButton(false);

        // Subscribe to Future on bottomSheetController and WHEN it triggers closed,
        // then bottom sheet is closed so call method to show FAB again
        bottomSheetController.closed.then((value) async {
          // Issue when fab flashes as it does not wait for animation of bottom sheet to finish
          // So as a workaround, when closing the bottom sheet, we wait a little time before showing fab again
          await Future.delayed(const Duration(milliseconds: 300));
          showFloatingActionButton(true);
        });

      },
    )
    // If not showing fab, show empty container
    : Container();
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: qualityA truly polished experiencef: material designflutter/packages/flutter/material repository.found in release: 3.3Found to occur in 3.3found in release: 3.7Found to occur in 3.7frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onteam-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions