mydomain
No ADS
No ADS

FlutterArtist Manual Sorting ReorderableGridView Example

  1. Install the library
  2. Structure of the example
  3. Currency37aShelf
  4. Currency37aReorderableGridItemsView
In our previous article, we explored manual sorting on lists (ReorderableListView). However, for grid-based interfaces, we need a more powerful solution: ReorderableGridView.
Note: Dragging and dropping ITEM(s) of ReorderableGridView does not seem to be as smooth and easy as ReorderableListView. You need to touch and hold the ITEM firmly for 1 second before dragging it to another location.
  • Download FlutterArtist Demo

1. Install the library

Important Note: Unlike ReorderableListView which is built-in, ReorderableGridView is a utility from a third-party library. You must add the dependency to your project:
pubspec.yaml
dependencies:
  reorderable_grid_view: ^2.2.6
No ADS

2. Structure of the example

3. Currency37aShelf

In FlutterArtist, to enable manual reordering of ITEM(s) on the client-side, the prerequisite is setting the sorting strategy in BlockConfig to SortStrategy.manual.
currency37a_shelf.dart
class Currency37aShelf extends Shelf {
  @override
  ShelfStructure defineShelfStructure() {
    return ShelfStructure(
      filterModels: {},
      blocks: [
        Currency37aBlock(
          name: Currency37aBlock.blkName,
          description: null,
          config: BlockConfig(clientSideSortStrategy: SortStrategy.manual),
          filterModelName: null,
          formModel: null,
          childBlocks: [],
        ),
      ],
    );
  }

  Currency37aBlock findCurrency37aBlock() {
    return findBlock(Currency37aBlock.blkName) as Currency37aBlock;
  }
}
No ADS
See more automatic sorting examples based on SortModel:

4. Currency37aReorderableGridItemsView

currency37a_reorderable_grid_items_view.dart
class Currency37aReorderableGridItemsView
    extends BlockItemsView<Currency37aBlock> {
  const Currency37aReorderableGridItemsView({
    required super.block,
    super.key,
  });

  @override
  Widget buildContent(BuildContext context) {
    List<CurrencyInfo> currencyInfos = block.items;
    //
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        final double minBoxWidth = 170;
        final int boxCount = constraints.constrainWidth() ~/ minBoxWidth;
        //
        final double boxHeight = 120;
        final double boxWidth = constraints.constrainWidth() / boxCount;
        final childAspectRatio = boxWidth / boxHeight;

        return ReorderableGridView.count(
            onReorder: (int oldIndex, int newIndex) {
              block.moveItemByIndexPosition(
                oldIndexPosition: oldIndex,
                newIndexPosition: newIndex,
              );
            },
            crossAxisCount: boxCount,
            mainAxisExtent: boxHeight,
            childAspectRatio: childAspectRatio,
            scrollSpeedController: (
              int timeInMilliSecond,
              double overSize,
              double itemSize,
            ) {
              // IMPORTANT:
              // Fix Error: The position being added has a smaller timestamp than...
              // https://github.com/huhuang03/reorderable_grid_view/blob/master/example/lib/demo/demo_reorderable_count.dart
              if (timeInMilliSecond > 1500) {
                return 15;
              } else {
                return 5;
              }
            },
            dragWidgetBuilderV2: DragWidgetBuilderV2(
              isScreenshotDragWidget: true,
              builder: (index, child, screenshot) {
                return child;
              },
            ),
            children: currencyInfos
                .map(
                  (currencyInfo) => Currency37aBox(
                    key: Key("Currency-${currencyInfo.id}"),
                    currencyInfo: currencyInfo,
                    selected: block.isCurrentItem(currencyInfo),
                    onCurrencyPressed: _onCurrencyPressed,
                  ),
                )
                .toList());
      },
    );
  }

  Future<void> _onCurrencyPressed(CurrencyInfo currencyInfo) async {
    // Write Log:
    FlutterArtist.codeFlowLogger.addMethodCall(
      ownerClassInstance: this,
      currentStackTrace: StackTrace.current,
      parameters: null,
    );
    // IMPORTANT:
    // - Call this method when the user clicks on an ITEM in the list.
    await block.refreshItemAndSetAsCurrent(
      item: currencyInfo,
      navigate: null,
    );
  }
}
No ADS
No ADS