Skip to main content

How to Create an AppBar with Round Bottom in Flutter

An AppBar is a bar at the top of the screen that provides navigation and contextual actions for an app. It can be either a standard AppBar or a SliverAppBar. In this post, we’ll explore how to create an AppBar with a round bottom in Flutter.

There are multiple ways to achieve this, but the most straightforward way is to RoundedRectangleBorder for an AppBar’s shape property.

Another method is to use ClipPath to create a custom clipping region for the AppBar. This approach gives us more control over the shape of the AppBar and we can use it to create other shapes as well, such as an oval or a heart.

For more complicated shapes or positions, it is advised to use a Stack and position the AppBar at the top of the stack. Then, we can add a Container with a bottom edge radius to give it a rounded bottom.

class RoundAppBar extends StatelessWidget with PreferredSizeWidget{
  final double barHeight = 50;
  final String title;

  RoundAppBar({Key key, this.title}) : super(key: key);

  @override
  Size get preferredSize => Size.fromHeight(kToolbarHeight + barHeight);

  @override
  Widget build(BuildContext context) {
    return AppBar(
      title: Center(child: Text(title)),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(
          bottom: Radius.circular(48.0),
        ),
      ),
      actions: [
        Icon(Icons.dehaze)
      ],
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(child: Text('Round AppBar')),
        backgroundColor: Colors.lightGreen,
        elevation: 0,
        actions: [Icon(Icons.dehaze_sharp)],
      ),
      body: SafeArea(
          child: Column(
        children: [
          ClipPath(
            clipper: RoundShape(),
            child: Container(
              height: 40,
              color: Colors.lightGreen,
            ),
          ),
          Center(
            child: Text('Body'),
          ),
        ],
      )),
    );
  }
}

class RoundShape extends CustomClipper<Path> {
  @override
  getClip(Size size) {
    double height = size.height;
    double width = size.width;
    double curveHeight = size.height / 2;

    var p = Path();
    p.lineTo(0, height - curveHeight);
    p.quadraticBezierTo(width / 2, height, width, height - curveHeight);
    p.lineTo(width, 0);
    p.close();

    return p;
  }

  @override
  bool shouldReclip(CustomClipper oldClipper) => true;
}

By continuing to use the site, you agree to the use of cookies.