The following code is the custom Bottom Nav Bar that I have created, and I want it to hide when the user scrolls down and pop back up only when the user scrolls back up.
Quite similar to the behaviour of the twitter/X bottom nav bar.
class CustomBottomNavbar extends StatefulWidget {
final int currentIndex;
final void Function(int index) onTap;
const CustomBottomNavbar({
Key? key,
required this.currentIndex,
required this.onTap,
}) : super(key: key);
@override
_CustomBottomNavbarState createState() => _CustomBottomNavbarState();
}
class _CustomBottomNavbarState extends State<CustomBottomNavbar> {
bool _isVisible = false;
int _tappedIndex = -1;
@override
void initState() {
super.initState();
Future.delayed(const Duration(milliseconds: 600), () {
setState(() {
_isVisible = true;
});
});
}
@override
Widget build(BuildContext context) {
return AnimatedPositioned(
duration: const Duration(milliseconds: 800),
curve: Curves.easeInOut,
bottom: _isVisible ? 0 : -800,
left: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 48.0),
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 1),
end: const Offset(0, 0),
).animate(
CurvedAnimation(
parent: ModalRoute.of(context)!.animation!,
curve: Curves.easeOut,
),
),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: Colors.grey[200]!.withOpacity(0.95),
),
height: 60.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
buildNavItem(Icons.home, 0),
buildNavItem(Icons.explore, 1),
buildNavItem(Icons.notifications, 2),
buildNavItem(Icons.account_circle, 3),
],
),
),
),
),
);
}
Widget buildNavItem(IconData icon, int index) {
final isSelected = index == widget.currentIndex;
double iconSize = _tappedIndex == index ? 40.0 : 32.0;
Color iconColor = isSelected
? Colors.grey[900]!
: (_tappedIndex == index ? Colors.black : Colors.grey[500]!);
return GestureDetector(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 60.0,
height: 60.0,
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 1200),
child: Icon(
icon,
key: ValueKey<IconData>(icon),
color: iconColor,
size: iconSize,
),
),
),
],
),
onTapDown: (_) {
setState(() {
_tappedIndex = index;
});
},
onTapUp: (_) {
setState(() {
_tappedIndex = -1;
});
widget.onTap(index);
},
onTapCancel: () {
setState(() {
_tappedIndex = -1;
});
},
);
}
}
Currently what this code does is:
- Initially shows an animation of the bottom nav bar popping up when the user opens the app.
- Hides when the user scrolls either up or down.
- After the user scrolls, the bottom nav bar stays hidden for about 3 seconds and pops back up.
What I want to achieve is, that the bottom nav bar stays hidden until the user scrolls up.
And shows up ONLY when the user scrolls up (with an animation).
Hope this isn’t too much to ask, but I have been stuck on this problem for quite a few weeks and can’t find a good solution.
Any help would be appreciated!
2
Answers
Try this
The _scrollController is used to detect the user’s scroll direction, and _isVisible is updated accordingly, adjust the _scrollThreshold variable to control how much the user needs to scroll before the bottom navbar reacts.
Try this creative way.
Widget
without any transition animation.Scaffold
in that page you want place bottomNavBar. Inbody
use any type of scrolling widget that you want and assign ascrollController
to that.floatingActionButton
field.Visibility
widget. and define a isVisible variable that you can change it inscrollController.listener()
.