DEV Community

loading...

Pinterest Floating Navigation Bar with Animations in Flutter

Neat Fastro
Software dev Freelancer Flutter enthusiast
・2 min read

In this short tutorial we will learn how to create the Navigation Bar of Pinterest App with hiding and reappearing behavior on user scroll.

This how our starting setup up looks like:

Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemBuilder: (BuildContext context, int index) {
          return SizedBox(
            height: 260,
            child: Card(
              child: Center(child: Text('Item #$index')),
            ),
          );
        },
      ),
      bottomNavigationBar: SizedBox(
        height: 60,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Icon(Icons.home),
            Icon(Icons.search),
            Icon(Icons.favorite_border),
            Icon(Icons.person_rounded),
          ],
        ),
      ),
    );
  }
Enter fullscreen mode Exit fullscreen mode
  1. Wrap Scaffold widget in NotificationListener<ScrollUpdateNotification>() widget with "ScrollUpdateNotification" type,

  2. This gives you a "ScrollUpdateNotification" object in a callBack function which gets executed when the user attempts scrolling on the screen.

  3. Now Wrap your BottomNavigationBar in Animated Container and specify the transform: property like this:

 AnimatedContainer(
          duration: Duration(milliseconds: 300),
        > transform: Matrix4.translationValues(0, yTransValue,0),
          child: BottomNavBarWidget(),
        ),
Enter fullscreen mode Exit fullscreen mode
  1. Make a variable of type "double" with appropriate name (yTransValue) and set it's value to 0

  2. onNotification callBack check the sign value of scroll delta
    if it is equal to 1 then it means user has swiped up on the screen and if it's -1 then user has swiped down on the screen.

onNotification: (notification) {
        if (notification.scrollDelta.sign == 1) {
          setState(() {
            yTransValue = 100;
          });
        } else if (notification.scrollDelta.sign == -1) {
          setState(() {
            yTransValue = 0;
          });
        }
      },
Enter fullscreen mode Exit fullscreen mode

and we are done.

Here's the complete code:

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  double yTransValue = 0;

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollUpdateNotification>(
      onNotification: (notification) {
        print(notification.metrics.axisDirection);
        print(notification.metrics.axis);

        if (notification.scrollDelta.sign == 1) {
          setState(() {
            yTransValue = 100;
          });
        } else if (notification.scrollDelta.sign == -1) {
          setState(() {
            yTransValue = 0;
          });
        }
      },
      child: Scaffold(
        body: ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            return SizedBox(
              height: 260,
              child: Card(
                child: Center(child: Text('Item #$index')),
              ),
            );
          },
        ),
        bottomNavigationBar: AnimatedContainer(
          duration: Duration(milliseconds: 300),
          transform: Matrix4.translationValues(0, yTransValue, 0),
          child: SizedBox(
            height: 60,
            child: Card(
              color: Colors.grey,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Icon(Icons.home),
                  Icon(Icons.search),
                  Icon(Icons.favorite_border),
                  Icon(Icons.person_rounded),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

code result video

Discussion (0)