'How to change appbar when listened to Bloc, I dont want to bloc builder on the scaffold, instead I want BlocBuidler on the AppBar?

Scaffold(
        // extendBodyBehindAppBar: true,
        // extendBody: true,
        appBar: AppBar(
          centerTitle: false,
          brightness: Brightness.light,
          leading: IconButton(
              icon: const Icon(
                Icons.arrow_back,
              ),
              onPressed: () {
                Navigator.pop(context);
              }),
          title: const Text(
            'Go back',
          ),
          elevation: 0,
          backgroundColor: Colors.transparent,
        ),
      .
      .
      .
      bottomNavigationBar: BottomNavigationWidget()
    )//Scaffold;

Simply, I want to change my app bar when the bottom navigation item is changed.. I am unable to wrap AppBar with the BlocBuilder<>, How can I achieve this?



Solution 1:[1]

Inside Scaffold widget you can use

appBar: PreferredSize(
  child: CustomAppBar(),
  preferredSize: Size.fromHeight(56),
),

And create another function or class as CustomAppBar which returns AppBar

return AppBar(
  title: Text(
    text ?? "Default Text",
  ),
);

And pass the text as parameter and if it is null you can set some default text for it.

Solution 2:[2]

The best solution is to wrap your AppBar with a BlocBuilder and wrap your BlocBuilder with Preferred Size. credit: jurej1 on GitHub.

appBar: PreferredSize(
    preferredSize: const Size.fromHeight(56),
    child: BlocBuilder<TurfBloc, TurfState>(
      builder: (context, state) {
        return AppBar(
          centerTitle: true,
          title: Text(state.text),
          backgroundColor: state.color,
        );
      },
    ),
  ),

Solution 3:[3]

You can't, as Scaffold appBar property accept widgets that extend PreferredSizeWidget class. Wrap Scaffold with BlocBuilder and depending on Bloc state just change AppBar properties:

return BlocBuilder<YourBloc, YourState>(
  builder: (context, state) => Scaffold(
    appBar: AppBar(
      title: state is Selected1 ? Text('Title1') : Text('TitleElse'),
      elevation: state is Selected1 ? 0 : 1
      )
    )
  );

Eventually create new widget that extend PreferredSizeWidget:

  class MyAppBar extends StatelessWidget with PreferredSizeWidget {
    @override
    Widget build(BuildContext context) {
      return BlocBuilder<YourBloc, YourState>(
        builder: (context, state) { 
          if(state is Selected1) {
            return AppBar(...);
          } else if (state is Selected2) {
            return AppBar(...);
          } else {
            return AppBar(...);
          }
        }
      );
    }

  @override
  Size get preferredSize => Size(appbarwidth, appbarheight);
  }

and use it, but be sure you have BlocProvider<YourBloc> above Scaffold:

return Scaffold(appBar: MyAppBar());

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tanharpatel
Solution 2 BigMarty
Solution 3 Paul Kastel