【问题标题】:Flutter SliverGrid Flip AxisFlutter SliverGrid 翻转轴
【发布时间】: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


    【解决方案1】:

    由于我使用SliverGridDelegateWithMaxCrossAxisExtent 作为我的网格委托,我只是将其子类化并稍微修改了getLayout 方法。

    class CrossAxisFlippedSliverGridDelegateWithMaxCrossAxisExtent
        extends SliverGridDelegateWithMaxCrossAxisExtent {
      /// Creates a delegate that makes grid layouts with tiles that have a maximum
      /// cross-axis extent and are flipped along the cross axis.
      /// ...
      const CrossAxisFlippedSliverGridDelegateWithMaxCrossAxisExtent({
        ...
        }) : super(...);
    
      @override
      SliverGridLayout getLayout(SliverConstraints constraints) {
        var tileLayout = super.getLayout(constraints) as SliverGridRegularTileLayout;
    
        return SliverGridRegularTileLayout(
          crossAxisCount: tileLayout.crossAxisCount,
          mainAxisStride: tileLayout.mainAxisStride,
          crossAxisStride: tileLayout.crossAxisStride,
          childMainAxisExtent: tileLayout.childMainAxisExtent,
          childCrossAxisExtent: tileLayout.childCrossAxisExtent,
    
          // Where the actual magic happens
          reverseCrossAxis: !tileLayout.reverseCrossAxis,
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-03
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 2022-06-23
      • 2021-02-13
      • 2011-09-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多