flutter_reorderable_grid_view

repository·master·Indexed 41 days ago

https://github.com/karvulf/flutter-reorderable-grid-view

A Flutter package providing animated drag-and-drop functionality for GridViews, including smooth animations for adding, removing, or resizing items. It features the ReorderableBuilder for implementing reorderable grids, ReorderableBuilderController for state management, and ReorderableAnimationConfig for customizing animation durations and curves.

Tokens
10.3K
Snippets
18
Records
32
Agent score
51%

What's inside flutter_reorderable_grid_view

  1. Supported GridView widgets for ReorderableBuilder

    master

    Depending on which constructor of ReorderableBuilder you use, different GridView types are supported:

    • ReorderableBuilder: Supports GridView, GridView.count, and GridView.extent.
    • ReorderableBuilder.builder: Supports GridView.builder (via the childBuilder parameter).
  2. Understand the types of animations in ReorderableGridView

    master

    The package provides two distinct animation behaviors:

    1. Drag and Drop: Ensures smooth positioning of the dragged child to any target position (unless that position is locked). It also animates the movement of other children while the drag is in progress.
    2. List Updates: Occurs when the underlying list of children is modified (adding, removing, or modifying items). This animates the repositioning of existing children to accommodate the changes.
  3. Customize iOS Launch Screen Assets

    master

    To change the launch screen image for the iOS version of your Flutter app, you can either replace the image files directly in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory or use Xcode for a more visual approach.

    Using Xcode:

    1. Open the iOS workspace by running open ios/Runner.xcworkspace from your terminal.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog to replace the existing launch images.
    open ios/Runner.xcworkspace
  4. Implement animated drag-and-drop with ReorderableBuilder

    master

    To add drag-and-drop functionality to a GridView, wrap your grid in a ReorderableBuilder.

    Key Requirements:

    1. Unique Keys: Every child within the GridView must have a unique Key.
    2. onReorder Callback: You must implement the onReorder callback to update your underlying data source. The callback provides a ReorderedListFunction, which you pass your list to in order to receive the new reordered list.
    3. ScrollController: If your GridView is scrollable, you must assign the same ScrollController instance to both the ReorderableBuilder and the GridView itself.

    Note on Scrolling: If the ReorderableBuilder is inside another scrollable widget, do not manually assign a ScrollController; it will automatically look up the existing one in the context. Manually assigning one in a nested scrollable context can break drag-and-drop functionality.

    import 'package:flutter/material.dart';
    import 'package:flutter_reorderable_grid_view/widgets/widgets.dart';
    
    // ... inside your State class ...
    final _scrollController = ScrollController();
    var _fruits = <String>["apple", "banana", "strawberry"];
    
    @override
    Widget build(BuildContext context) {
      final generatedChildren = List.generate(
        _fruits.length,
        (index) => Container(
          key: Key(_fruits[index]), // Unique key is required
          color: Colors.lightBlue,
          child: Text(_fruits[index]),
        ),
      );
    
      return Scaffold(
        body: ReorderableBuilder(
          children: generatedChildren,
          scrollController: _scrollController,
          onReorder: (ReorderedListFunction reorderedListFunction) {
            setState(() {
              // Update your data source using the returned list
              _fruits = reorderedListFunction(_fruits) as List<String>;
            });
          },
          builder: (children) {
            return GridView(
              controller: _scrollController, // Must match ReorderableBuilder controller
              children: children,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 4,
              ),
            );
          },
        ),
      );
    }
  5. Use ReorderableDragAndDropController for drag and drop management

    master
    The ReorderableDragAndDropController is a specialized controller used to manage the state and interactions of drag-and-drop operations within a reorderable grid. It handles collision detection between the dragged item and other items, manages item swapping, and calculates the necessary updates to reorder a list while respecting lockedIndices (indices that cannot be moved).
  6. Requirements for ReorderableEntity tracking

    master

    For ReorderableBuilderController to track and animate children correctly, the following constraints must be met:

    1. Unique ValueKeys: Every child widget passed to initChildren or updateChildren must have a ValueKey assigned to its key property.
    2. Key Uniqueness: Keys must be unique within the children list. The controller asserts that no duplicate keys exist in the childrenKeyMap.
    3. State Synchronization: The updateChildren method must be invoked following any modification to the underlying data source that changes the widget list to maintain correct animation mappings.
  7. Use CustomDraggable to wrap grid children

    master

    The CustomDraggable widget is a helper that can contain optional information to be added to Draggable or LongPressDraggable.

    Important: You must wrap the child you intend to add to your GridView with CustomDraggable, and the CustomDraggable itself must receive the unique key.

    CustomDraggable(
      // add your unique key here
      key: Key('unique'),
      // will be passed to `Draggable` or `LongPressDraggable`
      data: 'data',
      child: Placeholder(),
    ),
  8. Configure scrolling while dragging

    master

    The ReorderableBuilder supports automatic scrolling when a dragged item is moved near the edges of the scrollable area:

    • enableScrollingWhileDragging: Enables/disables automatic scrolling (default: true).
    • automaticScrollExtent: Defines the distance (in logical pixels) from the top or bottom edge at which automatic scrolling begins (default: 80.0).
    • scrollController: If the builder returns a scrollable widget (like GridView), you must pass the same ScrollController to both the ReorderableBuilder and the scrollable widget to ensure correct position calculations.
  9. Configure drag-and-drop behavior and constraints

    master

    The ReorderableBuilder provides several parameters to control how items are dragged and moved:

    • lockedIndices: Indices of items that cannot be moved and will not change position during a drag operation.
    • nonDraggableIndices: Indices of items that cannot be used to start a drag, but can still be moved to new positions by other items.
    • enableLongPress: Whether to require a long press to start dragging (default: true). Set longPressDelay to Duration.zero to enable immediate dragging.
    • enableDraggable: Enables/disables the entire drag-and-drop system. If true, onReorder or onReorderPositions must be provided.
    • feedbackScaleFactor: The scale applied to the widget being dragged (e.g., 1.05 grows the widget by 5%).
    • reverse: Set to true if your list is in reverse order. You must update this flag if the list order changes.
  10. Reference: ReorderableBuilder parameters

    master

    The following parameters are available for configuring the reorderable grid behavior. Note: Always provide a unique Key for every child widget.

    | **Parameter**                  | **Description**                                                                                                           | **Default Value** |
    |:-------------------------------|:--------------------------------------------------------------------------------------------------------------------------|:-----------------:|
    | `children`                     | Displays all given children that are build inside a Wrap or GridView. Don't forget a unique key for every child.       |       **-**       |
    | `childBuilder`                 | Enable support for [GridView.builder] using this function. Don't forget a unique key for every child.                   |       **-**       |
    | `lockedIndices`                | Define all children that can't be moved while dragging. You need to add the index of this child in a list.              |    **<int>[]**    |
    | `nonDraggableIndices`          | Specify indices for [children] that are not draggable.                                                                   |    **<int>[]**    |
    | `animationConfig`              | Configuration for all child animations (fade in, position changes, drag feedback, release animation).                   | `const ReorderableAnimationConfig()` |
    | `enableLongPress`              | Deprecated. Use `longPressDelay`; for immediate drag set `Duration.zero`.                                                |     **true**       |
    | `longPressDelay`               | Specify the duration before dragging starts after long-pressing the widget.                                              |    **500 ms**    |
    | `enableDraggable`              | Enables the drag and drop functionality.                                                                                 |     **true**       |
    | `enableScrollingWhileDragging` | Enables the functionality to scroll while dragging a child to the top or bottom.                                        |     **true**       |
    | `automaticScrollExtent`        | Defines the height of the top or bottom before the dragged child indicates a scrolling.                               |    **150.0**       |
    | `dragChildBoxDecoration`       | When a child is dragged, you can override the default BoxDecoration of the dragged child.                                |       **-**       |
    | `reverse`                      | Handles the reversed order of your children. Ensure to add this flag to your scrollable and this widget.                |     **false**     |
    | `builder`                      | It's required to use [ReorderableBuilder] to obtain updated [children].                                              |       **-**       |
    | `onReorder`                    | After releasing the dragged child, [onReorder] is called which contains a function as parameter to reorder all items.   |       **-**       |
    | `onDragStarted`                | Callback when dragging starts with the index where it started.                                                           |       **-**       |
    | `onDragEnd`                    | Callback when the dragged child was released with the index.                                                           |       **-**       |
    | `onUpdatedDraggedChild`        | Called when the dragged child has updated his position while dragging.                                                   |       **-**       |
    | `scrollController`             | `ScrollController` which should be also assigned to the scrollable widget. Don't forget this to prevent animation issues.|       **-**       |