reorderables

repository·master·Indexed 20 days ago

https://github.com/hanshengchiu/reorderables

A Flutter package providing a collection of widgets that support drag-and-drop reordering for various layouts. It includes reorderable versions of rows, columns, wraps, tables, and sliver lists, such as ReorderableRow, ReorderableColumn, ReorderableWrap, ReorderableTable, and ReorderableSliverList. The package also provides ReorderableFlex for custom one-dimensional draggable arrays.

Tokens
7.3K
Snippets
19
Records
30
Agent score
73%

What's inside reorderables

  1. How reorderable widgets work

    master

    The reorderables package provides various widgets (such as ReorderableTable, ReorderableRow, ReorderableColumn, ReorderableWrap, and ReorderableSliverList) that enable drag-and-drop reordering of their children.

    To implement reordering, the parent widget must provide an onReorder callback function. This function is invoked whenever a child is moved, providing the old index and the new index of the reordered child.

  2. Use ReorderableColumn

    master

    A reorderable version of Flutter's Column. It supports optional header and footer widgets and allows for custom crossAxisAlignment. It can be used inside an IntrinsicWidth widget to create list-like views that adapt to their content width.

    ReorderableColumn(
      header: Text('HEADER'),
      footer: Text('FOOTER'),
      crossAxisAlignment: CrossAxisAlignment.start,
      children: _rows,
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          Widget row = _rows.removeAt(oldIndex);
          _rows.insert(newIndex, row);
        });
      },
    )
  3. Use ReorderableWrap

    master

    A reorderable version of Flutter's Wrap. It supports size-based wrapping and can also limit the minimum and maximum amount of children in each run.

    Note: Since v0.2.5, children of ReorderableWrap do not need to have an explicit key specified.

    ReorderableWrap(
      spacing: 8.0,
      runSpacing: 4.0,
      padding: const EdgeInsets.all(8),
      children: _tiles,
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          Widget row = _tiles.removeAt(oldIndex);
          _tiles.insert(newIndex, row);
        });
      },
      onNoReorder: (int index) {
        // Optional callback when reorder is cancelled
      },
      onReorderStarted: (int index) {
        // Optional callback when reorder starts
      },
    )
  4. Explore reorderables package examples

    master

    The reorderables_example project provides several implementation patterns for using the reorderables package in Flutter. You can find specific implementation details in the following files:

    • ReorderableTable: See lib/table_example.dart
    • ReorderableWrap: See lib/wrap_example.dart
    • Nested ReorderableWrap: See lib/nested_wrap_example.dart
    • ReorderableColumn: See lib/column_example1.dart and lib/column_example2.dart
    • ReorderableRow: See lib/row_example.dart
    • ReorderableSliverList: See lib/sliver_example.dart
  5. Customize iOS launch screen assets

    master

    To change the launch screen image for your iOS application, you can either replace the image files directly in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory or use Xcode to manage the assets.

    To use Xcode:

    1. Open your Flutter project's iOS workspace using open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  6. Use ReorderableTable

    master

    A reorderable version of Flutter's Table. Unlike a list, cells in a table are horizontally aligned across rows.

    To make rows draggable, each row must be a ReorderableTableRow and every row must specify a key. This ensures the framework can track the identity of the rows during reordering.

    ReorderableTable(
      header: ReorderableTableRow(
        children: [Text('Name'), Text('Math')],
      ),
      children: _itemRows.map((row) => ReorderableTableRow(
        key: ObjectKey(row), // A key is required for each row
        children: [Text('Alex'), Text('D')],
      )).toList(),
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          ReorderableTableRow row = _itemRows.removeAt(oldIndex);
          _itemRows.insert(newIndex, row);
        });
      },
    )
  7. Use ReorderableSliverList

    master

    A reorderable version of Flutter's SliverList. To implement it, replace SliverList with ReorderableSliverList and use either ReorderableSliverChildListDelegate or ReorderableSliverChildBuilderDelegate instead of the standard Sliver delegates.

    Important: You must attach a ScrollController to the ScrollView (e.g., CustomScrollView) containing the ReorderableSliverList, otherwise an error will be thrown during dragging.

    ReorderableSliverList(
      delegate: ReorderableSliverChildListDelegate(_rows),
      // or
      // delegate: ReorderableSliverChildBuilderDelegate(
      //   (BuildContext context, int index) => _rows[index],
      //   childCount: _rows.length
      // ),
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          Widget row = _rows.removeAt(oldIndex);
          _rows.insert(newIndex, row);
        });
      },
    )
  8. Use ReorderableWrap for reorderable wrap layouts

    master

    The ReorderableWrap widget allows you to create a layout where children are wrapped (similar to a standard Wrap widget) but can also be reordered via drag-and-drop. It supports both horizontal and vertical directions and provides built-in support for drag feedback and layout animations during reordering.

    Key features include:

    • Directional Support: Works with Axis.horizontal or Axis.vertical.
    • Custom Containers: You can provide a buildItemsContainer to customize how the wrapped children are contained.
    • Header and Footer: Supports optional header and footer widgets.
    • Scroll Control: Integrates with SingleChildScrollView for scrolling behavior.

    Note: The widget relies on ContainedDraggable to identify which children are allowed to be reordered.

    ReorderableWrap(
      direction: Axis.horizontal,
      spacing: 8.0,
      runSpacing: 8.0,
      children: [
        // Children must be wrapped in ContainedDraggable to be reorderable
        ContainedDraggable(
          isReorderable: true,
          builder: (context) => MyWidget(),
        ),
        // ...
      ],
    );
  9. Use ReorderableSliverList for drag-and-drop sliver lists

    master

    A ReorderableSliverList is a widget that allows users to reorder children in a linear array along the main axis within a scrollable area. It is designed to be used inside a CustomScrollView.

    Important Requirements:

    • You must explicitly provide a ScrollController to the CustomScrollView that contains the ReorderableSliverList. If the controller is not provided, reordering will not work.
    • The list uses a SliverChildDelegate to lazily construct children.

    Key Properties:

    • delegate: A SliverChildDelegate (typically ReorderableSliverChildListDelegate or ReorderableSliverChildBuilderDelegate) that provides the children.
    • onReorder: A callback triggered when a child is dropped into a new position. It provides the startIndex and endIndex.
    • enabled: A boolean to enable or disable reordering (defaults to true).
    • buildDraggableFeedback: An optional builder to customize the widget that follows the user's finger during a drag.
    CustomScrollView(
      // A ScrollController must be included in CustomScrollView, otherwise
      // ReorderableSliverList won't work
      controller: _scrollController,
      slivers: <Widget>[
        SliverAppBar(
          expandedHeight: 210.0,
          flexibleSpace: FlexibleSpaceBar(
            title: Text('ReorderableSliverList'),
            background: Image.network('...'),
          ),
        ),
        ReorderableSliverList(
          delegate: ReorderableSliverChildListDelegate(_rows),
          // or use ReorderableSliverChildBuilderDelegate if needed
          // delegate: ReorderableSliverChildBuilderDelegate(
          //   (BuildContext context, int index) => _rows[index],
          //   childCount: _rows.length
          // ),
          onReorder: _onReorder,
        )
      ],
    )