Easy Q: explanation of CircularNotchedRectangle class

So, I’m new to Flutter and, just for the hell of it really, I’m playing around trying to reconfigure the BottomAppBar class. The thing is, I can’t for the life of me figure out how the CircularNotchedRectangle class gets visibility of the FAB rectangle location in order to calculate the notch.

BottomAppBar sourdce is here: flutter/bottom_app_bar.dart at f4abaa0735eba4dfd8f33f73363911d63931fe03 · flutter/flutter · GitHub

CircularNotchedRectangle source is here: flutter/notched_shapes.dart at f4abaa0735eba4dfd8f33f73363911d63931fe03 · flutter/flutter · GitHub

The line Path getOuterPath(Rect host, Rect? guest) in the CircularNotchedRectangle source takes information about the bottom app bar shape (Rect host) and information about the FAB (Rect? guest), depending on whether it intersects or not, but where do these values enter the class because these variables don’t appear in the constructor?

Can anyone help please? Would really appreciate it…

1 Like

Okay, so I thought I would try to post a minimum working example that highlights my question…

I grabbed the source for _DemoBottomAppBar from here, removed all the buttons and stuff, and what you see below is the result.

My question is this: how does the one and only instance of CircularNotchedRectangle() inside the _DemoBottomAppBar class get information about the FAB within the _BottomAppBarDemoState widget higher up the tree when nothing is passed explicitly?

I’m sure this is an easy Q for you clever people out there. I’d really appreciate some help as I would like to understand this so that I can perhaps look at increasing the number of FABs as a mini-project.

Thanks in advance.

import 'package:flutter/material.dart';

void main() {
  runApp(const BottomAppBarDemo());
}

class BottomAppBarDemo extends StatefulWidget {
  const BottomAppBarDemo({Key? key}) : super(key: key);
  @override
  State createState() => _BottomAppBarDemoState();
}

class _BottomAppBarDemoState extends State<BottomAppBarDemo> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          title: const Text('Bottom App Bar Demo'),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: const Icon(Icons.add),
          tooltip: 'Create',
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        bottomNavigationBar: _DemoBottomAppBar(
        ),
      ),
    );
  }
}

class _DemoBottomAppBar extends StatelessWidget {
  const _DemoBottomAppBar();
  @override
  Widget build(BuildContext context) {
    return BottomAppBar(
      shape: CircularNotchedRectangle(),
      color: Colors.blue,
      child: IconTheme(
        data: IconThemeData(color: Theme.of(context).colorScheme.onPrimary),
        child: Row(
          children: <Widget>[
            IconButton(
              tooltip: 'Open navigation menu',
              icon: const Icon(Icons.menu),
              onPressed: () {},
            ),
          ],
        ),
      ),
    );
  }

1 Like

Okay, so I thought I would post an update because I think I may have solved it. If I’m right then the answer is easy.

Essentially we pass the CircularNotchedRectangle() class into the BottomAppBar constructor so that CircularNotchedRectangle.getOuterPath() can be accessed within some method bound to the BottomAppBar class. That’s how CircularNotchedRectangle can access variables which are not specifically passed to its constructor.

Hope this helps anyone who might be interested.

2 Likes

Thanks for sharing! @BigDeeEss