【发布时间】:2021-12-14 01:05:57
【问题描述】:
tl;dr 如何在 SliverGrid 中翻转 X 轴?
我必须在网格中显示一个长列表(每个单元格的大小都相同)。我可以从带有分页的服务器请求列表。现在用户应该能够在网格中的任何索引处打开该列表,并且应该能够双向滚动。
我正在尝试在 Flutter 中创建一个 GridView,并在滚动时在两个方向(向上和向下)延迟加载其内容。
我的第一次尝试是将infinite_listview 修改为gridview。一开始看起来很有希望,但问题是min and maxExtend was overridden to be always negative and positive infinite。我将其改回正常行为,但只有 maxExtend 工作,minExtend 始终为 0,因此我无法向上滚动网格。
我的第二次尝试是带有视口的 Scrollable。在视口中,我放置了两个 SliverGrid(一个向上生长,一个向下生长)。我将视口的中心键设置为第二个 SliverGrid 的键,因此向下增长的 SliverGrid 的第一个项目是屏幕上的第一个单元格,用户可以滚动查看上方和下方的单元格。通过这种方法,滚动扩展保持不变。所以用户只能滚动直到他到达列表的末尾(或已经收到的单元格的末尾)。
class BidirectionalGridView extends StatelessWidget {
static const Key centerKey = ValueKey("CENTER");
final SliverGridDelegate gridDelegate;
final IndexedWidgetBuilder itemBuilder;
final int upperItemCount;
final int lowerItemCount;
const BidirectionalGridView({
required this.gridDelegate,
required this.itemBuilder,
required this.upperItemCount,
required this.lowerItemCount,
Key? key,
}) : super(key: key);
int get totalItemCount => upperItemCount + lowerItemCount;
@override
Widget build(BuildContext context) {
return Scrollable(
axisDirection: AxisDirection.down,
viewportBuilder: (context, position) {
return Builder(builder: (context) {
return Viewport(
center: centerKey,
offset: position,
anchor: 0,
slivers: [
SliverGrid(
gridDelegate: gridDelegate,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return itemBuilder(context, upperItemCount - 1 - index);
}, childCount: upperItemCount),
),
SliverGrid(
key: centerKey,
gridDelegate: gridDelegate,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return itemBuilder(context, upperItemCount + index);
}, childCount: lowerItemCount),
),
]);
});
},
);
}
}
使用此设置,我面临的问题是我必须翻转上 SliverGrid 的 X 轴才能获得右上半部分的顺序。但我不知道怎么做。
如何在 SliverGrid 中翻转 X 轴? 或者实现上半部分从左到右递增的顺序? (我不知道每行的单元格数,据我所知,我无法通过在构建器中翻译索引来操纵顺序)。
演示代码:
var items = <int>[];
for (var i = 0; i < 300; ++i) {
items.add(i - 100);
}
/*
* ...
*/
BidirectionalGridView(
upperItemCount: 100,
lowerItemCount: 200,
itemBuilder: (context, index) {
return SizedBox.square(
dimension: 72,
child: Align(
alignment: Alignment.center,
child: Text("${items[index]}"),
),
);
},
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 72,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
childAspectRatio: 1,
),
),
【问题讨论】:
标签: flutter dart mobile flutter-sliver