Flutter - 如何在列表视图中居中小部件

85

我正在尝试将一个小部件居中放置在listView中。

我尝试了这个方法,但是Text('ABC')没有垂直居中。 我该怎么做才能实现这个目标呢?

new Scaffold(
  appBar: new AppBar(),
  body: new ListView(
    padding: const EdgeInsets.all(20.0),
    children: [
      new Center(
        child: new Text('ABC')
      )
    ]
  )
);

3
为什么你要使用 ListView 做那件事情? - Günter Zöchbauer
11个回答

164

垂直居中和水平居中:

Scaffold(
  appBar: new AppBar(),
  body: Center(
    child: new ListView(
      shrinkWrap: true,
        padding: const EdgeInsets.all(20.0),
        children: [
          Center(child: new Text('ABC'))
        ]
    ),
  ),
);

仅垂直居中

Scaffold(
  appBar: new AppBar(),
  body: Center(
    child: new ListView(
      shrinkWrap: true,
        padding: const EdgeInsets.all(20.0),
        children: [
          new Text('ABC')
        ]
    ),
  ),
);

3
谢谢分享。这有效。但我有一个子项列表,所以我必须在每个子项上放置一个中心小部件 :( 希望Flutter在ListView上增加一个对齐属性... - Johan Walhout
1
感谢您的帮助!这正是我需要的! - MarcusOuelletus
8
这个方法可行,但 shrinkWrap: true 会导致页面不可滚动。 - Tuan van Duong
这对我没有用,而且你用来实现这个结果的逻辑绝对不清楚,请添加一些注释。 - Philippe Fanaro
2
在iOS中,你仍然可以滚动,但效果不佳。 - Youssef El Behi

64
使用 shrinkWrap = true 解决这个问题是一种hack。 在ListView中居中小部件的全部意义在于启用反弹和滚动。 使用shrinkWrap不能实现此目的,它在视觉上看起来正确,但行为完全错误。 解决方法是将一个Container作为ListView中唯一的子项,并给它一个最小高度,等于可用高度(使用LayoutBuilder来测量小部件的最大高度)。 然后,你可以在Container的子项中放置一个CenterColumn(具有MainAxisAlignment.center),从那里您可以添加您打算对齐的任何小部件。 下面是解决问题示例的代码:
Scaffold(
  appBar: AppBar(),
  body: LayoutBuilder(
    builder: (context, constraints) => ListView(
      children: [
        Container(
          padding: const EdgeInsets.all(20.0),
          constraints: BoxConstraints(
            minHeight: constraints.maxHeight,
          ),
          child: Center(
            child: Text('ABC'),
          ),
        )
      ],
    ),
  ),
);

9
这是最好的答案,shrinkWrap可能不是你想要使用的,尽管理想情况下ListView应该有更好的实现方式。对于我的特定情况,我需要一个ListView,以便可以触发RefreshIndicator。谢谢。 - kapace
1
在我的情况下,这是唯一可行的解决方案。 我需要一个菜单置于列表视图顶部,并在中心显示ActivityIndicator。 谢谢。 - Kerim Amanov
1
不错的解决方案,除非你正在处理一个登录/注册表单(就像我一样)。在这里,你会发现键盘打开后会立即关闭。使用 shrinkView: true 就不会出现这个问题。使用键盘是唯一强迫我使用 ListView 而不是 Column 的事情。 - Hamza Abbad
1
谢谢!这让我疯了,现在我知道该怎么做了,我真是太蠢了,之前居然没想到。 - BHinkson
1
运行得很好!但是为了让这个解决方案适用于我的用例,我不得不将“列的mainAxisSize”设置为“mainAxisSize.max”。 - Godwin Mathias
显示剩余4条评论

23

将你的小部件放入容器中

Container(alignment: Alignment.center, ...)
或者
Container(alignment: Alignment.centerLeft, ...)

13

enter image description here


只需将您的小部件包裹在Align中,并相应地提供alignment

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView( // your ListView
        children: <Widget>[
          Align(
            alignment: Alignment.centerLeft,
            child: _button("Left"),
          ),
          Align(
            alignment: Alignment.center,
            child: _button("Middle"),
          ),
          Align(
            alignment: Alignment.centerRight,
            child: _button("Right"),
          ),
        ],
      ),
    );
  }

  Widget _button(text) => RaisedButton(onPressed: () {}, child: Text(text));
}

12

使用Align将 widget 放置在屏幕中央,可以在ListView内使用。不需要设置任何对齐属性,因为默认是居中对齐。

这将在屏幕中央添加ListView,随着列表项的增加,它将仍然从中心增长。

   Center(
        child: ListView.builder(
          shrinkWrap: true,
          scrollDirection: Axis.vertical, // Axis.horizontal for horizontal list view.
          itemCount: 2,
          itemBuilder: (ctx, index) {
            return Align(child: Text('Text'));
          },
        ),
      ),

输出:

输入图像说明


1
首先,您不需要将Center用作ListView的父级;其次,默认情况下,scrollDirection为垂直方向;第三,在我的解决方案中已经提供了Align以将小部件居中。我没有看到您的回答中有任何价值,因此应该删除,如果我有错请指正。 - CopsOnRoad
@CopsOnRoad:它将从屏幕中心绘制ListView,我知道问题是关于Listview下的小部件。这是另一种方法,在中心添加Listview以及子文本。 - Jitesh Mohite
所以,你只想为问题将 Center 添加到你的 ListView 中,对吗?即使这样,你也是不正确的,无论你是否将你的 ListView 包装在 Center 中,都不会有任何区别。因此,你的答案实际上没有任何意义。如果我错了,请再次纠正我。 - CopsOnRoad
它确实将小部件居中了,但是ListView仍然无法滚动。 - Anonymous-E

2
只需使用Align小部件即可将子小部件垂直和/或水平居中:
   Align(
    alignment: Alignment.center,
    child: Text(
      'middle',
    ),

请注意:如果您有一个作为子级的列,您将需要添加“:”。
mainAxisAlignment: MainAxisAlignment.center 

将列垂直对齐。

1
最简单、最优雅的方法是使用ClampingScrollPhysics,这样只有在需要时才能滚动内容。 示例:
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ListView(
          physics: const ClampingScrollPhysics(),
            shrinkWrap: true,
            padding: const EdgeInsets.all(24),
            children: <Widget>[
.... your list of widgets ...
            ],
        ),
      ),
    );
  }

0
    child: ListView.builder(
                      shrinkWrap: true,
                      itemCount: Doctor.listOfDoctors.length,
                      itemBuilder: (BuildContext context, int index) {
                        String name = Doctor.listOfDoctors[index].name;
                        String details = Doctor.listOfDoctors[index].info;
                        //better for design is to use ListTile instead of Text Widget
                        return ListTile(
                          title: Text(
                            name,
//this is how I solved this issue ;)
                            **textAlign: TextAlign.center,**
                          ),

0
如果您需要将中心项目滚动,则请执行以下操作。
Center(
  child: ListView(
    shrinkWrap: true,
    children: [
      // the container with height will make the screen scroll
      Container(
        height:
             MediaQuery.of(context).size.height / 1.2,
        child: Text('ABC'),
      ),
    ],
  ),
),

提示:给容器一个颜色以可视化滚动区域


-1
将此容器添加到您的列表视图中。
Container(
            height: MediaQuery.of(context).size.height / 1.2,
            child: Center(
              child: Text(
                "No Record Found",
                style: TextStyle(fontSize: 20, color: Colors.black),
              ),
            ),
          ),

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