列表视图,滚动页脚在底部

Bra*_*sen 7 dart flutter

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

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

非页面填充列表视图 页面填写列表视图

我尝试计算listview需要的垂直大小,但这意味着我需要知道构建时孩子的高度.有没有更好的办法?

编辑
我试图为达到同样的事情在这里但当然颤振.

小智 8

这可以通过使用来实现SingleChildScrollView特殊的限制,如解释在这里

看看下面的例子:

@override
Widget build(BuildContext context) {
  return LayoutBuilder(
    builder: (BuildContext context, BoxConstraints constraints) {
      return SingleChildScrollView(
        child: ConstrainedBox(
          constraints: constraints.copyWith(
            minHeight: constraints.maxHeight,
            maxHeight: double.infinity,
          ),
          child: IntrinsicHeight(
            child: Column(
              children: <Widget>[
                Container(height: 200, color: Colors.blue),
                Container(height: 200, color: Colors.orange),
                Container(height: 200, color: Colors.green),
                Container(height: 50, color: Colors.pink),
                Expanded(
                  child: Align(
                    alignment: Alignment.bottomCenter,
                    child: Container(
                      width: double.infinity,
                      color: Colors.red,
                      padding: EdgeInsets.all(12.0),
                      child: Text('FOOTER', textAlign: TextAlign.center,),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }
  );
}

Run Code Online (Sandbox Code Playgroud)

这将构建以下布局: 在此处输入图片说明

如果您将粉红色容器的高度更改为更大的值,例如 500,您将看到页脚也随整个列表一起滚动。

感谢 Simon Lightfoot 的帮助,为我指明了正确的方向!


Rém*_*let 7

您需要为此创建自定义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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我改变了一件事

  • 不受约束的孩子maxExtent.因为如果没有更多的屏幕空间可用,那将对页脚强制执行0的高度.
  • SliverGeometry scrollExtent从"全屏高度" 更改为"实际可用尺寸".因此它实际上只填充剩余的可见空间.没有填满屏幕.
  • 添加了一个最小值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,
        ),
      ),
    ),
  ],
),
Run Code Online (Sandbox Code Playgroud)

  • 您应该考虑为此发出拉取请求。这应该是 Flutter 存储库 imo 的一部分。 (3认同)
  • 同意.我会做的. (3认同)
  • @RémiRousselet 您创建 PR 了吗?后来如何? (2认同)