I have a list 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 visib
While Naveen's solution works perfectly, I didn't like the idea of using setState
to handle the visibility of the navbar. Every time the user would change scroll direction, the entire homepage including the appbar and body would rebuild which can be an expensive operation. I created a separate class to handle the visibility that uses a ValueNotifier
to track the current hidden status.
class HideNavbar {
final ScrollController controller = ScrollController();
ValueNotifier visible = ValueNotifier(true);
HideNavbar() {
visible.value = true;
controller.addListener(
() {
if (controller.position.userScrollDirection ==
ScrollDirection.reverse) {
if (visible.value) {
visible.value = false;
}
}
if (controller.position.userScrollDirection ==
ScrollDirection.forward) {
if (!visible.value) {
visible.value = true;
}
}
},
);
}
}
Now all you do is create a final instance of HideNavbar
in your HomePage widget.
final HideNavbar hiding = HideNavbar();
Now pass the instance's ScrollController
to the ListView
or CustomScrollView
body of your Scaffold
.
body: CustomScrollView(
controller: hiding.controller,
...
Then surround your bottomNavigationBar
with a ValueListenableBuilder
that takes the ValueNotifier
from the HideNavbar
instance and the set the height property of the bottomNavigationBar to be either 0 or any other value depending on the status of the ValueNotifier
.
bottomNavigationBar: ValueListenableBuilder(
valueListenable: hiding.visible,
builder: (context, bool value, child) => AnimatedContainer(
duration: Duration(milliseconds: 500),
height: value ? 56.0 : 0.0,
child: Wrap(
children: [
BottomNavigationBar(
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.blue,
fixedColor: Colors.white,
unselectedItemColor: Colors.white,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.card_giftcard),
title: Text('Offers'),
),
BottomNavigationBarItem(
icon: Icon(Icons.account_box),
title: Text('Account'),
),
],
),
],
),
),
),
This approaches keeps the HomePage as a StatelessWidget, avoids countless rebuilds, and doesn't require any external libraries. You can also implement this as a stream-based approach but that would require another library such as dart:async
and would not be changing anything.