How to add rounded corners to BottomAppBar with CircularNotchedRectangle in Flutter

4,180

You can create your own ShapeBorder.

enter image description here

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        extendBody: true,
        body: Container(
          color: Colors.amber,
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        floatingActionButton: Transform.translate(
          offset: Offset(0, -10),
          child: FloatingActionButton(
            onPressed: () {},
            child: Icon(Icons.add),
            elevation: 2.0,
          ),
        ),
        bottomNavigationBar: BottomNavigationView(),
      ),
    );
  }
}

class BottomNavigationView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Transform.translate(
      offset: Offset(0.0, -10),
      child: Container(
        margin: EdgeInsets.symmetric(horizontal: 10),
        padding: EdgeInsets.symmetric(horizontal: 20),
        decoration: ShapeDecoration(
          color: Colors.white,
          shape: MyBorderShape(),
          shadows: [
            BoxShadow(
                color: Colors.black38, blurRadius: 8.0, offset: Offset(1, 1)),
          ],
        ),
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Icon(Icons.accessibility_new),
              ],
            ),
            _buildMiddleTabItem(),
            Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Icon(Icons.accessibility_new),
              ],
            )
          ],
        ),
      ),
    );
  }

  Widget _buildMiddleTabItem() {
    return Expanded(
      child: SizedBox(
        height: 60,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SizedBox(height: 24),
            Text(''),
          ],
        ),
      ),
    );
  }
}

class MyBorderShape extends ShapeBorder {
  MyBorderShape();

  @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.zero;

  @override
  Path getInnerPath(Rect rect, {TextDirection textDirection}) => null;

  double holeSize = 70;

  @override
  Path getOuterPath(Rect rect, {TextDirection textDirection}) {
    print(rect.height);
    return Path.combine(
      PathOperation.difference,
      Path()
        ..addRRect(
            RRect.fromRectAndRadius(rect, Radius.circular(rect.height / 2)))
        ..close(),
      Path()
        ..addOval(Rect.fromCenter(
            center: rect.center.translate(0, -rect.height / 2),
            height: holeSize,
            width: holeSize))
        ..close(),
    );
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}

  @override
  ShapeBorder scale(double t) => this;
}
Share:
4,180
Da Artagnan
Author by

Da Artagnan

Updated on December 17, 2022

Comments

  • Da Artagnan
    Da Artagnan over 1 year

    I want to create BottomAppBar with rounded corners, circular notched rectangle and material shadow. The problem is that when I add rounded corners to BottomAppBar by wrapping it with ClipRRect widget I lose material shadow.

    BottomAppBar without rounded corners, but with Material shadow. Please ignore wrong aligned notch. enter image description here

    BottomAppBar wrapped in ClipRRect widget, but without shadow. Again please ignore wrong aligned notch: enter image description here

    How to achieve rounded corners with notch and material shadow?

    Full code:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          home: Scaffold(
            extendBody: true,
            body: Container(
              color: Colors.amber,
            ),
            floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
            floatingActionButton: Transform.translate(
              offset: Offset(0, -10),
              child: FloatingActionButton(
                onPressed: () {},
                child: Icon(Icons.add),
                elevation: 2.0,
              ),
            ),
            bottomNavigationBar: BottomNavigationView(),
          ),
        );
      }
    }
    
    class BottomNavigationView extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return Transform.translate(
          offset: Offset(0.0, -10),
          child: Container(
            margin: EdgeInsets.only(left: 20, right: 20),
            child: ClipRRect(
              borderRadius: BorderRadius.all(Radius.circular(30),
              ),
              child: BottomAppBar(
                shape: CircularNotchedRectangle(),
                child: Row(
                  mainAxisSize: MainAxisSize.max,
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: <Widget>[
                    Column(
                      mainAxisSize: MainAxisSize.min,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Icon(Icons.accessibility_new),
                      ],
                    ),
                    _buildMiddleTabItem(),
                    Column(
                      mainAxisSize: MainAxisSize.min,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Icon(Icons.accessibility_new),
                      ],
                    )
                  ],
                ),
              ),
            ),
          ),
        );
      }
    
      Widget _buildMiddleTabItem() {
        return Expanded(
          child: SizedBox(
            height: 60,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                SizedBox(height: 24),
                Text(''),
              ],
            ),
          ),
        );
      }
    }