flutter 底部带有滚动页脚的列表视图

smdncfj3  于 2022-11-25  发布在  Flutter
关注(0)|答案(4)|浏览(177)

我正在尝试创建一个滚动列表小部件,它可以显示一些项目,并能够在滚动的底部添加页脚。
如果滚动列表没有占据整个高度,比如只有2个条目,那么页脚仍然应该出现在屏幕的底部。
第一次
我试着计算列表视图所需的垂直尺寸,但这意味着我需要在构建时知道子视图的高度。有更好的方法吗?

编辑

我试图达到与here完全相同的效果,当然是使用Flutter。

bakd9h0s

bakd9h0s1#

您需要为此创建一个自定义的RenderBox。因为没有现成的小部件支持这个功能。
SliverFillRemaining非常接近。但是它的大小调整/滚动行为与您所期望的不同。As,如果存在,几乎总是使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。
  • SliverGeometryscrollExtent从“全屏高度”更改为“实际可用大小”。这样它实际上只 * 填充 * 剩余的可见空间。而不是填充屏幕。
  • 将最小值添加到相同的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,
        ),
      ),
    ),
  ],
),
hgqdbh6s

hgqdbh6s2#

这可以通过使用具有特殊约束的SingleChildScrollView来实现,如here所解释的。
请看下面的例子:

@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,),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }
  );
}

这将生成以下布局:

如果您将粉红色容器的高度更改为更大的值,例如500,您将看到页脚也随整个列表一起滚动。
感谢西蒙·莱特富特的帮助,为我指明了正确的方向!

hgtggwj0

hgtggwj03#

使用生成器在ListView中添加页脚
1.只需在itemCount中添加+1,例如:itemCount:list.length + 1
1.在返回customWidget时,检查条件list.length == index,仅返回SizedBox(height:"required height of footer ")
编码:

ListView.builder(
itemCount: list.length+1,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
  return GestureDetector(
      onTap: () {
        if (list.length == index) {
          return;
        }
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => PlotDetail(list[index])));
      },
      child: list.length != index?PlotListItemWidget(list[index]):SizedBox(height: 100,));
   },
);
cdmah0mi

cdmah0mi4#

这里我创建了flat_list小部件,它的规范与React Native的FlatList类似。

FlatList(
+  listFooterWidget: const Footer(),
  data: items.value,
  buildItem: (item, index) {
    var person = items.value[index];

    return ListItemView(person: person);
  },
),

相关问题