gpt4 book ai didi

flutter - 我如何检测小部件在呈现之前是否会溢出其约束?

转载 作者:行者123 更新时间:2023-12-05 04:59:41 24 4
gpt4 key购买 nike

我有一个 PageView我想用它在列中显示无限数量的小部件。我正在尝试向列中添加小部件,直到它溢出,然后从可能溢出的小部件开始构建下一页。

Diagram of problem

到目前为止,这是我为了让某些东西正常工作而拼凑起来的东西:

class OverflowSliverChildDelegate extends SliverChildDelegate {
OverflowSliverChildDelegate({
@required this.itemBuilder,
}) : assert(itemBuilder != null),
super();

/// Used to build individual items to slot into pages.
final IndexedWidgetBuilder itemBuilder;

@override
Widget build(BuildContext context, int index) {
return LayoutBuilder(
builder: (context, constraints) {
// todo: handle this better
if (remainingHeight <= 0) throw Error();

var itemIndex = 0;
return PageView.builder(
itemBuilder: (context, pageIndex) {
final remainingHeight = constraints.maxHeight;
return Column(
// todo: move this generator to a separate method
children: () sync* {
// Build widgets until we run out of vertical space.
while (remainingHeight > 0) {
// todo: layout widget and get its height
final widget = itemBuilder(context, itemIndex++);

// remainingHeight -= widget.height

yield widget;
}
}(),
);
},
);
},
);
}
}

如果我只关心文本,我可以使用 TextPainter 来布置文本并获取高度。有没有办法对任意小部件(可能有也可能没有自己的 child )执行此操作?


更新

查看 Offstage 小部件后,我尝试了这个,但 Flutter 断言我没有从对象外部调用 size getter。我也觉得离解决方案很近了。

          while (remainingHeight > 0) {
final widget = itemBuilder(context, itemIndex++);

final renderObj = ConstrainedBox(
child: widget,
constraints: constraints.copyWith(
maxHeight: remainingHeight,
),
).createRenderObject(context);

renderObj.layout(constraints);

remainingHeight -= renderObj.size.height;

if (remainingHeight > 0) {
yield widget;
}
}

最佳答案

我最终深入研究了 Flutter 的 sliver list 源代码(本质上是 ListView 小部件的后端)并且我能够弄清楚它是如何决定何时有足够的 child 来填充视口(viewport)的和“缓存范围”。

为了尝试不同的方法,我已经开始了一个新的 Flutter 项目,但我已经对其进行了一些清理并将其发布到 pub.dev:https://pub.dev/packages/overflow_page_view

结果是一个 PageView,它为每个页面构建一个 CustomScrollView。我直接从 Flutter 源代码中复制了 RenderSliv​​er 的代码,并更改了其子项的布局部分。理想情况下,我希望找到一种方法将自定义 SliverConstraints 传递给 ListView 或其他 sliver 小部件。


关于回答“如何检测小部件在呈现之前是否会溢出其约束?”这个问题:

我将 RenderSliv​​erList 的代码复制到我自己的类 (NoCacheRenderSliv​​erList) 中并开始调整。应该注意的是,我使用了 NeverScrollableScrollPhysics,这样我就不必担心滚动(因为我不需要它)。

首先,在 performLayout 方法的顶部,我将 targetEndScrollOffset 更改为剩余的绘制范围,与滚动偏移或缓存无关程度。这里只关心可见区域:

final double targetEndScrollOffset = this.constraints.remainingPaintExtent;

接下来,我需要更改嵌套的 bool advance() 方法以在子项的底部超出视口(viewport)边缘时返回 false:

  assert(child != null);
final SliverMultiBoxAdaptorParentData childParentData =
child.parentData as SliverMultiBoxAdaptorParentData;
childParentData.layoutOffset = endScrollOffset;
assert(childParentData.index == index);
// In the original source, this is assigned directly to endScrollOffset
final tmp = childScrollOffset(child) + paintExtentOf(child);
if (tmp > targetEndScrollOffset) {
return false;
}
endScrollOffset = tmp;
return true;

使用上面的代码,我们最终仍然会显示一个超出视口(viewport)的子项。我最后的改变是确保这个 child 被垃圾收集:

  // Finally count up all the remaining children and label them as garbage.
if (child != null) {
// By commenting out this line, we ensure the final child is garbage collected.
// child = childAfter(child);
while (child != null) {
trailingGarbage += 1;
child = childAfter(child);
}
}

这就是它的全部。如果有人有任何改进或需要澄清,我很乐意对此进行更新。

关于flutter - 我如何检测小部件在呈现之前是否会溢出其约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63415589/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com