Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to vertically center text/title in Flutter using SliverAppBar?

I am trying to set up a SliverAppBar in a CustomScrollView using Flutter, and can't get to vertically center the title.

I already tried this solution (and this SO question is exactly what I want to do) but fortunately, it didn't work for me.

Here is my build method:

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: CustomScrollView(
      slivers: <Widget>[
        SliverAppBar(
          pinned: true,
          expandedHeight: 200,
          //backgroundColor: Colors.transparent,
          flexibleSpace: FlexibleSpaceBar(
            titlePadding: EdgeInsets.zero,
            centerTitle: true,
            title: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Text("Should be centered", textAlign: TextAlign.center),
              ],
            ),
            background: Image.asset("assets/earth.jpg", fit: BoxFit.cover),
          ),
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.menu),
              tooltip: "Menu",
              onPressed: () {
                // onPressed handler
              },
            ),
          ],
        ),
        SliverFixedExtentList(
          itemExtent: 50,
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              return Container(
                alignment: Alignment.center,
                color: Colors.green,
                child: Text("Index n°$index"),
              );
            },
          ),
        )
      ],
    ),
  );
}

I really don't understand what is wrong and why it isn't centered. I observed that the column is way too big when setting mainAxisSize to mainAxisSize.max.

Any idea?

Thanks in advance!

like image 687
BlueskyFR Avatar asked Dec 22 '22 23:12

BlueskyFR


1 Answers

I tinkered around a bit in your code and was able to center it. So the main problem here was the expandedHeight. This height expands the SliverAppBar both upwards and downwards meaning that half of that 200 was always above the screen. Taking that into consideration, you would be trying to center the text in only the bottom half of the app bar. The simplest way was to just use Flexible to size the items relative to their container. Here's the working code:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            expandedHeight: 200,
            //backgroundColor: Colors.transparent,
            flexibleSpace: FlexibleSpaceBar(
              titlePadding: EdgeInsets.zero,
              centerTitle: true,
              title: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Flexible(
                    flex: 3,
                    child: Container(),
                  ),
                  Flexible(
                    flex: 1,
                    child:
                        Text("Should be centered", textAlign: TextAlign.center),
                  ),
                  Flexible(
                    flex: 1,
                    child: Container(),
                  ),
                ],
              ),
              background: Image.asset("assets/earth.png", fit: BoxFit.cover),
            ),
            actions: <Widget>[
              IconButton(
                icon: const Icon(Icons.menu),
                tooltip: "Menu",
                onPressed: () {
                  // onPressed handler
                },
              ),
            ],
          ),
          SliverFixedExtentList(
            itemExtent: 50,
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  color: Colors.green,
                  child: Text("Index n°$index"),
                );
              },
            ),
          )
        ],
      ),
    );
  }

A way without empty containers

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            expandedHeight: 200,
            flexibleSpace: FlexibleSpaceBar(
              titlePadding: EdgeInsets.zero,
              centerTitle: true,
              title: SizedBox(
                height: 130,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text("Should be centered", textAlign: TextAlign.center),
                  ],
                ),
              ),
              background: Image.asset("assets/earth.png", fit: BoxFit.cover),
            ),
            actions: <Widget>[
              IconButton(
                icon: const Icon(Icons.menu),
                tooltip: "Menu",
                onPressed: () {
                  // onPressed handler
                },
              ),
            ],
          ),
          SliverFixedExtentList(
            itemExtent: 50,
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  color: Colors.green,
                  child: Text("Index n°$index"),
                );
              },
            ),
          )
        ],
      ),
    );
  }
like image 199
Sayegh Avatar answered Jan 12 '23 00:01

Sayegh