Rounded bottom on appbar

You can use BoxDecoration to add border-radius and shadow to a Container/DecoratedBox.

 new Container(
    height: 200.0,
    decoration: new BoxDecoration(
      color: Colors.orange,
      boxShadow: [
        new BoxShadow(blurRadius: 40.0)
      ],
      borderRadius: new BorderRadius.vertical(
          bottom: new Radius.elliptical(
              MediaQuery.of(context).size.width, 100.0)),
    ),
  ),

enter image description here

Although you may notice : That's not pixel perfect. The border is not an actual circle, but an ellipsis. Which may be undesired.

A more realistic, but more complex approach, is to draw a circle with a radius based on the width of your screen. Which will overflow the container. And then clip it.

You'll need a few things : LayoutBuilder, to get the width. ClipRect to not paint outside the container's constraints. And OverflowBox, to layout a circle that is larger than it's parent.

class RoundedAppBar extends StatelessWidget implements PreferredSizeWidget {
  @override
  Widget build(BuildContext context) {
    return new SizedBox.fromSize(
      size: preferredSize,
      child: new LayoutBuilder(builder: (context, constraint) {
        final width = constraint.maxWidth * 8;
        return new ClipRect(
          child: new OverflowBox(
            maxHeight: double.infinity,
            maxWidth: double.infinity,
            child: new SizedBox(
              width: width,
              height: width,
              child: new Padding(
                padding: new EdgeInsets.only(
                  bottom: width / 2 - preferredSize.height / 2),                    
                child: new DecoratedBox(
                  decoration: new BoxDecoration(
                    color: Colors.orange,
                    shape: BoxShape.circle,
                    boxShadow: [
                      new BoxShadow(color: Colors.black54, blurRadius: 10.0)
                    ],
                  ),
                ),
              ),
            ),
          ),
        );
      }),
    );
  }

  @override
  Size get preferredSize => const Size.fromHeight(200.0);
}

Centered on purpose, just to show how clip worksenter image description here


In Flutter you can have custom shape in AppBar widget with shape property.

  AppBar(
    title: Text('My App'),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.vertical(
        bottom: Radius.circular(30),
      ),
    ),
  ),

There is one simple way to achieve this using ClipPath -

  1. Apply background color to AppBar

  2. Create A SizedBox/Container of some height (say 240) right below AppBar in body and apply same background color

  3. Use ClipPath widget to wrap that SizedBox/Container

       ClipPath(
       clipper: CustomShape(), // this is my own class which extendsCustomClipper
       child: Container(
       height: 150,
       color: kPrimaryColor,
       ),
     ),
    

Now create a class like CustomShape which extends CustomClipper like below

class CustomShape extends CustomClipper<Path> {
  @override
  getClip(Size size) {
    double height = size.height;
    double width = size.width;
    var path = Path();
    path.lineTo(0, height - 50);
    path.quadraticBezierTo(width / 2, height, width, height - 50);
    path.lineTo(width, 0);
    path.close();
    
    return path;
 }

  @override
    bool shouldReclip(CustomClipper oldClipper) {
    return true;
 }
}

Change your heights fraction, I kept heights-50 for a nice curve you want

The output is like below -

enter image description here


Your above helped me a lot, I am just struggling with one thing, and that is to make the rounded bar a lot smaller in its height.

I change the height in this line

 Size get preferredSize => const Size.fromHeight(200.0);

but it doesn't affect it enough, i even set it down to 0 and still the bar is to high.

Tags:

Dart

Flutter