Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change AppBar height dynamically during runtime based on the AppBar content in Flutter?

I'm trying to implement a flutter_tagging inside the AppBar. I managed to add the tagged TextField inside the AppBar and to resize the AppBar using PreferredSize widget using the following code:

return PreferredSize(
    preferredSize: Size.fromHeight(110),
    child: AppBar(
      backgroundColor: HexColor('171551'),
      leading: const BackButton(),
      flexibleSpace: Padding(
        padding: const EdgeInsets.only(top: 48.0, left: 10, right: 10),
        child: buildTaggedSearch(),
      ),
      title: Container(),
      actions: _buildActions(),
    ),
  );

And this is the result:

enter image description here

The problem I can't manage to solve is what happens when user enter too many tags and the tags go to the second line, this is what happens:

enter image description here

I'm still new to Flutter and maybe I missing something, but how would I solve this issue and make the AppBar resize based on the content of the tags. I went over most of the questions here which talk about the AppBar resize, all of them use the PreferredSize widget which I use here. So I wonder if there is another option?

like image 769
Emil Adz Avatar asked Jan 30 '20 21:01

Emil Adz


People also ask

How do I change the size of the AppBar?

If you are in Visual Code, Ctrl + Click on AppBar function. And edit this piece. app_bar. dart will open and you can find preferredSize = new Size.

Can we increase the size of AppBar in flutter?

You can use PreferredSize and flexibleSpace for it like below: appBar: PreferredSize( preferredSize: Size.

What is default height of AppBar in flutter?

AppBar has a fixed height of 56.


2 Answers

There is no easy way to change the AppBar height at run-time. Yes, you can set it to any (fixed) height with PreferredSize, but once it's set, you normally cannot change it.

Even if you make your own class to extend PreferredSize, it will end up like this:

class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
  @override
  Size get preferredSize => Size.fromHeight(100); // fixed custom height

  @override
  Widget build(BuildContext context) {...}
}

This preferredSize getter needs to return a fixed size. Its parent widget (Scaffold) really wants to know the app bar height, so it knows where to start rendering its body.

And if you change the above "CustomAppBar" to Stateful, you will quickly realize the preferredSize you must override, is part of the Widget not the State.

And if you do some sort of hack, like using a global variable to "trick" it:

Size get preferredSize => Size.fromHeight(myAppBarHeight); // global variable

After changing the value in myAppBarHeight, the app bar still remains at its old height. You must call setState on widget with the Scaffold in order to redraw the app bar, and more importantly, redraw Scaffold body at a different position.

So really, the solution maybe is to control app bar height at the Scaffold level.

Or perhaps you should look into SliverAppBar.

Or do not try to change the app bar height at run-time, for example, use a ListView to horizontally scroll your chips.

Or build your own widget and don't use the app bar.

like image 183
user1032613 Avatar answered Nov 01 '22 09:11

user1032613


I was looking for this problem, I find a solution with NestedScrollView and a plugin SliverStickyHeader

Here is how I did this,

Scaffold(
  body: SafeArea(
    child: NestedScrollView(
      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return <Widget>[
          SliverStickyHeader(
            sticky: false,
            header: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                children: [
                  TextField(
                    decoration: InputDecoration(
                        hintText: 'Search', prefixIcon: Icon(Icons.search)),
                  ),
                  Container(
                    height: kToolbarHeight,
                    child: ListView.builder(
                      scrollDirection: Axis.horizontal,
                      itemBuilder: (context, i) {
                        return Center(
                          child: Container(
                            padding: EdgeInsets.all(8.0),
                            margin: EdgeInsets.symmetric(horizontal: 4.0),
                            decoration: BoxDecoration(
                              color: Theme.of(context)
                                  .primaryColor
                                  .withOpacity(0.5),
                              borderRadius: BorderRadius.circular(25.0),
                            ),
                            child: Row(
                              children: [
                                Text(
                                  'Tag $i',
                                  style: TextStyle(
                                    color: Colors.white,
                                  ),
                                ),
                                SizedBox(width: 8.0),
                                CircleAvatar(
                                  radius: 25.0 / 2,
                                  child: Icon(Icons.close),
                                )
                              ],
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),
          )
        ];
      },
      body: ListView.builder(itemBuilder: (context, i) {
        return ListTile(
          leading: CircleAvatar(child: Text('$i')),
          title: Text('Appbar with dynamic height'),
        );
      }),
    ),
  ),
);

and it is fulfilling my requirement, Plugin also support fully Sliver functionality, but I use it with as header only. I hope it will be helpful.

like image 39
Azhar Ali Avatar answered Nov 01 '22 08:11

Azhar Ali