我正在try 创建一个滚动列表小部件,它可以显示一些项目,并且能够在底部添加一个页脚,可以滚动.

如果滚动列表没有占据整个高度,例如只有两个项目,则页脚仍应显示在屏幕底部.以下是我试图实现的一些草图

non page filling listviewpage filling listview

我试着计算listview需要的垂直大小,但这意味着我需要知道构建时子元素们的身高.有更好的办法吗?

EDIT

推荐答案

您需要为此创建一个自定义RenderBox.因为没有开箱即用的小部件来支持这一点.

SliverFillRemaining已经非常接近了.但它的大小调整/滚动行为与您预期的不同.就像,如果有的话,几乎总是会让Scrollable…可滚动的.

取而代之的是,我们可以复制粘贴SliverFillRemaining个源码.并做一些编辑

class SliverFooter extends SingleChildRenderObjectWidget {
  /// Creates a sliver that fills the remaining space in the viewport.
  const SliverFooter({
    Key key,
    Widget child,
  }) : super(key: key, child: child);

  @override
  RenderSliverFooter createRenderObject(BuildContext context) => new RenderSliverFooter();
}

class RenderSliverFooter extends RenderSliverSingleBoxAdapter {
  /// Creates a [RenderSliver] that wraps a [RenderBox] which is sized to fit
  /// the remaining space in the viewport.
  RenderSliverFooter({
    RenderBox child,
  }) : super(child: child);

  @override
  void performLayout() {
    final extent = constraints.remainingPaintExtent - math.min(constraints.overlap, 0.0);
    var childGrowthSize = .0; // added
    if (child != null) {
       // changed maxExtent from 'extent' to double.infinity
      child.layout(constraints.asBoxConstraints(minExtent: extent, maxExtent: double.infinity), parentUsesSize: true);
      childGrowthSize = constraints.axis == Axis.vertical ? child.size.height : child.size.width; // added
    }
    final paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: extent);
    assert(paintedChildSize.isFinite);
    assert(paintedChildSize >= 0.0);
    geometry = new SliverGeometry(
      // used to be this : scrollExtent: constraints.viewportMainAxisExtent,
      scrollExtent: math.max(extent, childGrowthSize),
      paintExtent: paintedChildSize,
      maxPaintExtent: paintedChildSize,
      hasVisualOverflow: extent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
    );
    if (child != null) {
      setChildParentData(child, constraints, geometry);
    }
  }
}

在这里我改变了一件三件事

  • 不约束子maxExtent.因为如果没有更多的屏幕空间可用,将强制页脚高度为0.
  • SliverGeometry scrollExtent从"全屏高度"更改为"实际可用大小".所以它实际上只剩下fill个可见空间.而不是填满屏幕.
  • 将最小值添加到相同的scrollExtent,等于实际页脚高度.因此,如果视口中没有剩余空间,只需添加子对象,而不在其周围留有任何间距.

我们现在可以像往常一样在我们的CustomScrollView内使用它.

最终结果:

new CustomScrollView(
  slivers: <Widget>[
    new SliverFixedExtentList(
      itemExtent: 42.0,
      delegate: new SliverChildBuilderDelegate((context, index) {
        return new SizedBox.expand(
          child: new Card(),
        );
      }, childCount: 42),
    ),
    new SliverFooter(
      child: new Align(
        alignment: Alignment.bottomCenter,
        child: new Container(
          height: 42.0,
          color: Colors.red,
        ),
      ),
    ),
  ],
),

Flutter相关问答推荐

如何在flater中实现Notch?

使用Bg晃动背景图像边界

Flutter 中的面向对象模式

Flutter 布局-全屏幕容器

Flutter 对齐:不适用于多行文字

Flutter 翼doctor 显示的错误,我似乎不能修复.问题:系统32、Android工具链、Windows 10 SDK

BlocBuilder仅生成一次,并在后续发出时停止重建

BottomNavigationBar-我应该使用Container和Align吗?

将记录/元组用作SplayTreeMap中的键

Ffltter Firebase向用户添加公司

Flutter:在 pubspec.yaml 中找不到assets资源

如何从列表中更新provider变量:Flutter列表和Provider优化指南

如何从Firebase登录获取用户信息,如电话号码、出生日期和性别

PreferredSizeWidget类不能用作混合,因为它既不是混合类也不是混合

Paypal 支付网关添加带有 magento 2 网络详细信息用户名、密码、签名 Magento 2 的 flutter 应用程序?

Flutter/Riverpod 创建复杂对象的副本,其值在某处发生变化

在 flutter 的另一个类中使用变量值

如何在 flutter 的 onChanged(更改字符)处更改 TextField 边框 colored颜色 ?

在 Dart 中使用隔离时访问外部范围内的变量

配置项目:firebase_core时出现问题