Как вертикально центрировать текст/заголовок во Flutter с помощью SliverAppBar?

Я пытаюсь настроить SliverAppBar в CustomScrollView с помощью Flutter и не могу центрировать заголовок по вертикали.

Я уже пробовал это решение (и этот ТАК вопрос - именно то, что я хочу сделать), но, к счастью, это не сработало для меня.

Вот мой метод сборки:

@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"),
              );
            },
          ),
        )
      ],
    ),
  );
}

Я действительно не понимаю, что не так и почему это не по центру. Я заметил, что столбец слишком велик при установке для mainAxisSize значения mainAxisSize.max.

Есть идеи?

Заранее спасибо!


person BlueskyFR    schedule 18.04.2019    source источник


Ответы (3)


Я немного повозился с вашим кодом и смог его центрировать. Итак, основная проблема здесь заключалась в расширенной высоте. Эта высота расширяет SliverAppBar как вверх, так и вниз, что означает, что половина из этих 200 всегда была над экраном. Принимая это во внимание, вы попытаетесь центрировать текст только в нижней половине панели приложения. Самым простым способом было просто использовать Flexible для определения размера элементов относительно их контейнера. Вот рабочий код:

  @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"),
                );
              },
            ),
          )
        ],
      ),
    );
  }

Путь без пустых контейнеров

  @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"),
                );
              },
            ),
          )
        ],
      ),
    );
  }
person Sayegh    schedule 18.04.2019
comment
Спасибо за ваш ответ, но нет ли более чистого способа добиться того, чтобы не использовать 2 пустых гибких? - person BlueskyFR; 18.04.2019
comment
Обновил ответ более чистой версией. - person Sayegh; 19.04.2019
comment
Спасибо! Я завернул вторую часть вашего ответа в SafeArea, чтобы центрировать заголовок по вертикали в свернутом состоянии, и это отлично работает! - person BlueskyFR; 19.04.2019
comment
Рад, что смог быть полезен :) - person Sayegh; 19.04.2019

Вместо использования FlexibleSpaceBar используйте другой виджет.

flexibleSpace: Padding(
            padding: EdgeInsets.all(4),
            child: Container(),
            }),
          ),
person Pedro Romão    schedule 04.02.2021

Как и то, что ранее сказал Педро, вместо этого вы можете использовать параметр flexibleSpace в SliverAppBar, а затем центрировать его оттуда. Это то, что я сделал.

SliverAppBar(
    flexibleSpace: Center(
        child: Text("27 is my favorite number")
    )
 )
person Friedrick    schedule 28.04.2021