Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide Bottom Navigation bar on Scroll in Flutter

I have a list of blog posts in the body and bottom navigation bar. I want to hide bottom navigation bar with a slide down animation when the posts list is scrolled down and visible with a slide up animation when scrolled up. How to do it?

like image 638
Mohith7548 Avatar asked May 15 '18 15:05

Mohith7548


4 Answers

Try to wrap the ListView as the child of a NotificationListener and listen to scrolling events https://docs.flutter.io/flutter/widgets/OverscrollNotification-class.html

other approach is using ScrollUpdateNotification https://docs.flutter.io/flutter/widgets/ScrollUpdateNotification-class.html

like image 63
moonvader Avatar answered Oct 16 '22 01:10

moonvader


I was able to do it in my application using Provider. This is how I proceeded:

1- Create your provider class, that will have to method to switch the visibility of your bottom bar and notify the listeners:

class BottomBarVisibilityProvider extends ChangeNotifier {
  bool isVisible = true;

  void show() {
    if (!isVisible) {
      isVisible = true;
      notifyListeners();
    }
  }

  void hide() {
    if (isVisible) {
      isVisible = false;
      notifyListeners();
    }
  }
}

2- add a consumer of this class on top of your bottom bar, the AnimatedContainer will consume the visibility status from your provider and set if you want to display the bottomBar or not depending on the scroll direction of your scrollable widget:

  bottomNavigationBar: Consumer<BottomBarVisibilityProvider>(
    builder: (context, bottomBarVisibilityProvider, child) =>
        AnimatedContainer(
      duration: const Duration(milliseconds: 200),
      child: bottomBarVisibilityProvider.isVisible
          ? Wrap(
              children: const [BottomBar()],
            )
          : Wrap(),
    ),
  ),

3- Another consumer now, but for the scrollable widget: and note that in this widget your need to add a listener for your scrollController so your could change the visibility status in your provider depending on the user scroll direction:

          return Consumer<BottomBarVisibilityProvider>(
            builder: (context, bottomBarVisibilityProvider, child) {
              scrollController.addListener(() {
                final direction =
                    scrollController.position.userScrollDirection;

                if (direction == ScrollDirection.forward) {
                  if (!bottomBarVisibilityProvider.isVisible) {
                    bottomBarVisibilityProvider.show();
                  }
                } else if (direction == ScrollDirection.reverse) {
                  if (bottomBarVisibilityProvider.isVisible) {
                    bottomBarVisibilityProvider.hide();
                  }
                }
              });

              return ListView.builder(
                key: eventListKey,
                controller: scrollController,
                itemCount: snapshot.docs.length,
                itemBuilder: (context, index) {
                  return TravelCard(events.elementAt(index));
                },
              );
            },
          );

Happy fluttering!

like image 24
ExtraHassan Avatar answered Oct 16 '22 01:10

ExtraHassan


Use Hidable library

My team has a package called: hidable. Which basically makes it easy to add scroll-to-hide functionality to any static-located widget.

Depend on it:

dependencies:
  hidable: ^1.0.2

Create a scroll controller, inside your widget state:

final ScrollController scrollController = ScrollController();

Pass that scrollController to your scrollable widget - (ListView, SingleChildScrollView and etc.)

ListView(
  controller: scrollController,
  ...
)

Then wrap your BottomNavigationBar with the Hidable widget:

Hidable(
  controller: scrollController,
  wOpacity: true, // As default it's true.
  size: 56, // As default it's 56.
  child: BottomNavigationBar(...),
)

enter image description here

For more information refer to the Github page -> https://github.com/anonistas/hidable

like image 39
iss Avatar answered Oct 16 '22 01:10

iss


You need a ScrollController to monitor/observe the scroll direction of the Listview. The controller will be initialized in the initState and a listener should be added to it....The listener should toggle a boolean depending on the Scroll direction....Then the Bottom Naigatio Bar should be wrapped with an OffStage

This code should help


import 'package:flutter/material.dart';
import 'package:flutter/rendering.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 Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {

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

class _MyHomePageState extends State<MyHomePage> {

  bool _isVisible = true;
  ScrollController controller;


  @override
  void initState() {
    super.initState();
    controller = ScrollController();
    controller.addListener(() {
      setState(() {
        _isVisible = controller.position.userScrollDirection == ScrollDirection.forward;
      });
    });
  }



  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        controller: controller,
        children: List.generate(200, (index) => Text(("$index"))),
      ),
      bottomNavigationBar: Offstage(
        offstage: !_isVisible,
        child: BottomNavigationBar(
          items: [
            BottomNavigationBarItem(
              title: Text("Hello"),
              icon: Icon(Icons.style)
            ),
            BottomNavigationBarItem(
                title: Text("Hi"),
                icon: Icon(Icons.style)
            ),
            BottomNavigationBarItem(
                title: Text("Hey"),
                icon: Icon(Icons.style)
            )
          ],
        ),
      ),
    );
  }
}
like image 32
Josteve Avatar answered Oct 16 '22 03:10

Josteve