如何在Flutter中使用SliverAppBar垂直居中文本/标题?

4

我正在使用Flutter在CustomScrollView中设置SliverAppBar,并且无法使标题垂直居中。

我已经尝试了这个解决方案(这个问题正是我想做的),但不幸的是,它对我没有起作用。

以下是我的构建方法:

@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时,我发现该列太大了。

有任何想法吗?

提前致谢!

3个回答

9

我在您的代码中进行了一些修改,成功地将其居中。所以这里的主要问题是 expandedHeight。这个高度会使 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"),
                );
              },
            ),
          )
        ],
      ),
    );
  }

谢谢您的回复,但是难道没有更“简洁”的方法来实现不涉及2个空的Flexible吗? - BlueskyFR
更新了答案,提供了更清晰的版本。 - Sayegh
2
谢谢!我将你的回答中的第二部分用SafeArea包装起来,以在折叠时垂直居中标题,效果非常完美! - BlueskyFR
1
很高兴我能帮到你 :) - Sayegh

2

不要使用FlexibleSpaceBar,而是使用其他Widget。

flexibleSpace: Padding(
            padding: EdgeInsets.all(4),
            child: Container(),
            }),
          ),

2

就像Pedro之前说的那样,您可以在SliverAppBar中使用flexibleSpace参数,然后从那里居中对齐。这是我所做的。

SliverAppBar(
    flexibleSpace: Center(
        child: Text("27 is my favorite number")
    )
 )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接