Dart Flutter

Custom appbar in flutter

So, I’ve been using flutter to work on a side project for a while now. I, like many others, was dissatisfied with some of the flutter’s default widgets, and I suspect you will be as well. In this example, it’s the AppBar widget. 

If you’re unfamiliar with the AppBar, it’s a top-of-screen widget that normally displays the page title, certain popular activities, and the back arrow or drawer toggle. 

This is how the default appears.

The problem

I wanted a bespoke AppBar widget with custom colours, a custom leading icon, and a custom size that used the screen title as an input. I didn’t want to have to specify these variables every time I required an appBar, either. 

I was still unsatisfied with the method that most instructions suggested after going through multiple articles on how to design a custom AppBar. The majority of the articles I discovered suggested making a custom widget, similar to the one below, and placing it on top of your scaffold body.

class CustomAppBar extends StatelessWidget {
  final String title;

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

  @override
  Widget build(BuildContext context) {
    MediaQueryData mediaQuery = MediaQuery.of(context);
    double height =
        (mediaQuery.size.height - mediaQuery.padding.top) * HEADER_HEIGHT;
    return Container(
      height: height,
      child: Row(
        children: <Widget>[
          IconButton(
            color: Colors.black,
            icon: Icon(Icons.chevron_left),
            onPressed: () => Navigator.pop(context),
          ),
          Text(title)
        ],
      ),
    );
  }
}

This solution works (sort of), but I’m not a fan of it because it eliminates many, if not all, of the default AppBar’s fundamental capabilities and functions. 

Some blogs have suggested using one of the many custom app bar libraries available, but why manage yet another 3rd party library for a particular use case?

My Solution

The principle is: inherit all the default AppBar and override the ones you want to customize. Simple, right?

This was my approach:

Create a CustomAppBar stateless widget, that return the default AppBar, like so:

    class CustomAppBar extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
            return AppBar(
            );
        }
    }

This will allow us to add our CustomAppBar to the Scaffold in the correct way, which is:

Scaffold(
    appBar: CustomAppBar(SCREEN_TITLE),
        body: //your body here
)
Add your customization to the AppBar, like for example:

return AppBar(
    title: Text(
        title,
        style: TextStyle(color: Colors.black),
    ),
    backgroundColor: Colors.white,
    leading: IconButton(
        icon: Icon(Icons.chevron_left),
        onPressed: () => Navigator.pop(context),
        color: Colors.black,
    ),
);

If you wanted to, you could also set automaticallyImplyLeading here. In this case you would have something that looks like this:

return AppBar(
    title: Text(
        title,
        style: TextStyle(color: Colors.black),
    ),
    backgroundColor: Colors.white,
    automaticallyImplyLeading: true,
);

Theoretically, this should be enough but there is one more step. If you go on your Scaffold and add the CustomAppBar we just created you’ll get an error

argument_type_not_assignable -> The argument type ‘CustomAppBar’ can’t be assigned to the parameter type ‘PreferredSizeWidget’

This is because Scaffold doesn’t actually receive AppBar in its appBar property. Instead in takes in PreferredSizeWidget. So we need an extra step.

Extend PreferredSizeWidget. This is where you set the custom height of your CustomAppBar.

You will have to edit your constructor to account for this change. In the end, you should have something similar to this:

class CustomAppBar extends StatelessWidget with PreferredSizeWidget {
    @override
    final Size preferredSize;

    final String title;

    CustomAppBar(
        this.title,
        { Key key,}) : preferredSize = Size.fromHeight(50.0),
            super(key: key);

    @override
    Widget build(BuildContext context) {
        return AppBar(
            title: Text(
                title,
                style: TextStyle(color: Colors.black),
            ),
            backgroundColor: Colors.white,
            automaticallyImplyLeading: true,
        );
    }
}

Conclusion

By doing this you can get a custom AppBar with all the customization if you want without adding any 3rd party library. ­čÖé and this is what the end product looks like.

RECOMMENDED ARTICLES





Leave a Reply

Your email address will not be published. Required fields are marked *