繁体   English   中英

ListView Flutter 动态高度

[英]Flutter dynamic height of ListView

我正在开发一个Flutter应用程序,我想动态调整 ListView 的高度。

我希望列表的最大高度为200 如果高度超过这个值,用户将不得不滚动到底部。 如果高度低于200 ,它将只占用所需的空间。

应用预览:截图 如您所见, Restaurants nearby被推到页面的最底部。 我希望 ListView 只占用200或更小的高度,这样下面的内容就不会被推到底部。

这是我当前的代码:

@override
Widget build(BuildContext context) {
  return Container(
    padding: EdgeInsets.all(10.0),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text(
          'Restaurants nearby',
          style: TextStyle(
            fontSize: 20.0,
            fontWeight: FontWeight.bold,
          ),
        ),
        Divider(),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text('Enter restaurant manually'),
              onPressed: () {
                print('Button pressed');
              },
            ),
          ],
        ),
        Flexible(
          child: ListView.builder(
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                leading: CircleAvatar(
                  backgroundColor: Colors.cyan,
                ),
                title: Text('Test restaurant'),
                subtitle: Text('80m'),
              );
            },
            itemCount: 15,
          ),
        ),
        Text(
          'Restaurants nearby',
          style: TextStyle(
            fontSize: 20.0,
            fontWeight: FontWeight.bold,
          ),
        ),
      ],
    ),
  );
}

您正在使用Flexible的小部件,这就是您的ListView扩展的原因。 您必须将Flexible更改为ConstrainedBox并将shrinkWrap: true添加到您的ListView

ConstrainedBox(
  constraints: BoxConstraints(maxHeight: 200, minHeight: 56.0),
  child: ListView.builder(
    shrinkWrap: true,
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          leading: CircleAvatar(
            backgroundColor: Colors.cyan,
          ),
          title: Text('Test restaurant'),
          subtitle: Text('80m'),
        );
      },
    itemCount: 15,
  ),
),

更多信息: https ://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html

您可以使用LimitedBox

Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: <Widget>[
    Text(...),
    Divider(),
    Row(...),
    LimitedBox(
      maxHeight: 200.0,
      child: ListView.builder(...),
    ),
    Text(...),
  ],
),

在传入约束不受限制的情况下推荐的解决方案

考虑将ListView包装到这个

LimitedBox(
  maxHeight: 200,
  child: Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      Flexible(
        child: ListView.builder(
          shrinkWrap: true,
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              leading: CircleAvatar(
                backgroundColor: Colors.cyan,
              ),
              title: Text('Test restaurant'),
              subtitle: Text('80m'),
            );
          },
          itemCount: _itemsCount,
        ),
      ),
    ]
  )
),

注意:

  • ListViewshrinkWrap设置为true
  • ColumnmainAxisSize设置为MainAxisSize.min
  • LimitedBoxmaxHeight设置为200

一个完整的片段:

import 'package:flutter/material.dart';

class DebugWidget extends StatefulWidget {
  @override
  _DebugWidgetState createState() => _DebugWidgetState();
}
class _DebugWidgetState extends State<DebugWidget> {
  int _itemsCount = 1;

  @override
  Widget build(BuildContext context) {
    Widget child = Container(
      padding: EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            'Restaurants nearby',
            style: TextStyle(
              fontSize: 20.0,
              fontWeight: FontWeight.bold,
            ),
          ),
          Divider(),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              RaisedButton(
                child: Text('Enter restaurant manually'),
                onPressed: () {
                  print('Button pressed');
                },
              ),
              RaisedButton(
                child: Text('+1'),
                onPressed: () {
                  setState(() {
                    _itemsCount += 1;
                  });
                },
              ),
              RaisedButton(
                child: Text('-1'),
                onPressed: () {
                  setState(() {
                    _itemsCount -= 1;
                  });
                },
              ),
            ],
          ),
          LimitedBox(
            maxHeight: 200,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Flexible(
                  child: ListView.builder(
                    shrinkWrap: true,
                    itemBuilder: (BuildContext context, int index) {
                      return ListTile(
                        leading: CircleAvatar(
                          backgroundColor: Colors.cyan,
                        ),
                        title: Text('Test restaurant'),
                        subtitle: Text('80m'),
                      );
                    },
                    itemCount: _itemsCount,
                  ),
                ),
              ]
            )
          ),
          Text(
            'Restaurants nearby',
            style: TextStyle(
              fontSize: 20.0,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );

    return Scaffold(
      body: child,
    );
  }
}

我找到了解决这个问题的方法。 你应该用LimittedBox 或ConstraintBox 包装你的ListView 并给它们maxHeight 并将ListView 的shrinkWrap 属性设置为true。 解决方案是这样的。

LimitedBox(
          maxHeight: 200,
          child: ListView.builder(
            shrinkWrap: true,
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                leading: CircleAvatar(
                  backgroundColor: Colors.cyan,
                ),
                title: Text('Test restaurant'),
                subtitle: Text('80m'),
              );
            },
            itemCount: 15,
          ),
        ),
ConstrainedBox(
  constraints: BoxConstraints(maxHeight: 200.0),
  child: [your child here],
)

这使您的孩子的身高不大于200.0

我看到这个问题从来没有只通过给出一个固定的高度来回答,所以这对我有用。

出于某种原因,如果将shrinkwrap 设置为true,它看起来不像在工作,但确实如此,问题出在ListView 的填充设置中,将填充设置为edgeinstets.zero。 这为我解决了问题。

  • 包裹在一个灵活的内部
  • 收缩包装真
  • 填充,零
  • 如果需要,列到 MainAxisSize.min。

希望它可以帮助一些人。

我的代码示例:

Flexible(
                  child: Container(
                    decoration: BStyles.cardDecoration1,
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          const Text(
                            'PRODUCTION TASKS',
                          ),
                          const SizedBox(
                            height: textVerticalSpacing,
                          ),
                          Flexible(
                            child: ListView.builder(
                              itemCount: recentTasks.length,
                              padding: EdgeInsets.zero,
                              physics: const NeverScrollableScrollPhysics(),
                              shrinkWrap: true,
                              itemBuilder: (BuildContext context, int index) {
                                return TaskCard(
                                  task: recentTasks[index],
                                  widthInfo: MediaQuery.of(context).size.width * 0.6,
                                );
                              },
                            ),
                          ),
                          const SizedBox(
                            height: itemSpacing,
                          ),
                          Align(
                            alignment: Alignment.centerRight,
                            child: InkWell(
                              onTap: () { },
                              child: const Text(
                                'View more',
                              ),
                            ),
                          ),
                          const SizedBox(
                            height: textVerticalSpacing,
                          ),
                        ],
                      ),
                    ),
                  ),
                ),

您始终可以将 ListView 容器的大小设置为视口的百分比(当然假设其他小部件也以相同的方式调整大小):

return Container(
      height: MediaQuery.of(context).size.height * 0.75,
      child: ListView.builder(
        itemBuilder: (ctx, index) {
          return Card(...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM