在 Column Flutter 中居中展开 ListView

Posted

技术标签:

【中文标题】在 Column Flutter 中居中展开 ListView【英文标题】:Center Expanded ListView inside Column Flutter 【发布时间】:2019-05-03 19:22:46 【问题描述】:

我正在尝试构建一个布局,其中顶部和底部有两个 Text 对象,它们保持静止,一个 ListView 在它们的中心。

这是屏幕的代码

class HomeScreen extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: SafeArea(
        child: Container(
          padding: EdgeInsets.symmetric(horizontal: 40.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Container(
                margin: EdgeInsets.symmetric(vertical: 40.0),
                child: Text(
                  DateFormat("hh:mm 'PM ,'  MMMM d").format(DateTime.now()),
                  style: Theme.of(context).textTheme.title,
                ),
              ),
              Expanded(
                child: ListView.builder(
                  itemCount: 4,
                  itemBuilder: (BuildContext context, int index) =>
                      CustomAppText(
                        text: 'Custom App',
                      ),
                ),
              ),
              Container(
                margin: EdgeInsets.symmetric(vertical: 40.0),
                child: Text(
                  "Settings",
                  style: Theme.of(context).textTheme.title,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  

给定代码的输出

我正在寻找的设计

我尝试过使用 Center 小部件,但它没有使 ListView 居中

【问题讨论】:

【参考方案1】:

ListView 填充了整个 Expanded Widget,这就是为什么使用 Center 小部件不起作用的原因,所以应该添加 shrinkWrap: true,这样 ListView 只需要它的孩子的高度。

在浏览了我找到的关于灵活小部件的文档后

Flexible, which does not force the child to fill the available space.

做出改变并像魅力一样工作

Flexible(
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: 4,
                  itemBuilder: (BuildContext context, int index) =>
                      CustomAppText(
                        text: 'Custom App',
                      ),
                ),
              ),

【讨论】:

这实际上并不能解决问题。现在 ListView 没有展开,它只占用了足够的空间。 完美答案:) 完美答案...【参考方案2】:

对于那些仍在寻找答案的人,这对我有用:

Column(
  children: [

    Container(), // some top content

    Expanded(
      child: Center(
        child: ListView(
          shrinkWrap: true,
          children: [] //your list view content here
        )
      )
    ),

    Container(), // some bottom content

  ]
)

扩展小部件使内容占据所有可用空间。

Center 小部件将您要显示的内容居中。

ListView 保存您的列表内容,"shrinkWrap: true" 属性使您的列表视图根据内容大小缩小(允许它由 在不占用大量空间时居中小部件)。

【讨论】:

感谢您的解决方案和解释。【参考方案3】:

希望对您有所帮助。为顶部和底部小部件提供 25% 的屏幕尺寸。为列表视图设置屏幕大小的 50%。

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget 
  @override
  _TestPageState createState() => _TestPageState();


class _TestPageState extends State<TestPage> 
  @override
  Widget build(BuildContext context) 
    final _size = MediaQuery.of(context).size;

    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(28.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              // Top Widgets
              Container(
                width: double.infinity,
                // color: Colors.green,
                height: _size.height * 0.25, // Take 25% width of the screen height
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text('11: 25 AM', style: TextStyle(fontSize: 23.0),),
                    Text('Set As Launcher', style: TextStyle(fontSize: 23.0),)
                  ],
                ),
              ),

              Expanded(
                child: Container(
                  // color: Colors.yellow,
                  child: ListView(
                    children: List.generate(25, (index)
                      return Text('Custom App $index', style: TextStyle(fontSize: 45.0),);
                    ),
                  ),
                ),
              ),

              // Bottom Widgets
              Container(
                width: double.infinity,
                // color: Colors.blue,
                height: _size.height * 0.25, // Take 25% width of the screen height
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.end,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text('Settings', style: TextStyle(fontSize: 23.0),),                    
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
  

【讨论】:

【参考方案4】:

只需在Column 中添加一个Expanded 作为您的第一个Container 的包装器

        Expanded(
                        child: Container(
                          margin: EdgeInsets.symmetric(vertical: 40.0),
                          child: Text(
                            DateFormat("hh:mm 'PM ,'  MMMM d").format(DateTime.now()),
                            style: Theme.of(context).textTheme.title,
                          ),
                        ),
                      ),

【讨论】:

这会将整个列向下推到设置附近,而不是中心【参考方案5】:

只需将您的 ListView.builder 包装在一个容器类中并给它一个高度,明确地以双倍或屏幕高度的百分比表示。

class Trial extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: SafeArea(
        child: Container(
          padding: EdgeInsets.symmetric(horizontal: 40.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Container(
                margin: EdgeInsets.symmetric(vertical: 40.0),
                child: Text(
                  "Some Text",
                  style: Theme.of(context).textTheme.title,
                ),
              ),
              Container(
//                height: 40,
                height: MediaQuery.of(context).size.height * 0.4,
                child: ListView.builder(
                  itemCount: 20,
                  itemBuilder: (BuildContext context, int index) 
                    return Text("Hello");
                  
                ),
              ),
              Container(
                margin: EdgeInsets.symmetric(vertical: 40.0),
                child: Text(
                  "Settings",
                  style: Theme.of(context).textTheme.title,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  

【讨论】:

【参考方案6】:

添加两个垫片,它会给您 100% 与您预期相同的结果

      Spacer(),
          Expanded(
            child: ListView.builder(
              itemCount: 4,
              itemBuilder: (BuildContext context, int index) =>
                  CustomAppText(
                    text: 'Custom App',
                  ),
            ),
          ),
          Spacer(),

【讨论】:

【参考方案7】:

如果你用Container 替换你的Expanded 小部件并给它一个固定的height,我想你会得到你想要的。

【讨论】:

这意味着我必须明确提供一个高度,这是一个 hacky 解决方案 您需要将 CustomAppText 中的小部件居中,这看起来好像列表视图位于中心。

以上是关于在 Column Flutter 中居中展开 ListView的主要内容,如果未能解决你的问题,请参考以下文章

flutter - 网格视图不显示在展开的小部件中。

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

聊聊flutter的UI布局

展开的小部件必须放在 Flex 小部件内

如何在颤动中居中图表视图或树视图?

Flutter基础组件04Row/Column