multi_reorderable 0.2.0 copy "multi_reorderable: ^0.2.0" to clipboard
multi_reorderable: ^0.2.0 copied to clipboard

A Flutter package for multi-selection and animated reordering of items.

Multi Reorderable #

A powerful and customizable Flutter widget for multi-selection and animated reordering of items.

Portfolio

Work with me

Features #

  • Multi-selection: Select multiple items with checkboxes
  • Drag & Drop Reordering: Easily reorder items with smooth animations
  • Animated Stacking: Selected items stack visually when being dragged
  • Customizable UI: Extensive theming options and builder patterns
  • Selection Management: Built-in selection state management with callbacks
  • Auto-scrolling: Automatically scrolls when dragging near edges
  • Header & Footer Support: Add custom widgets above and below the list
  • Pagination Support: Load more items as the user scrolls, with state preservation
  • Pull-to-Refresh: Standard pull-to-refresh functionality for reloading data
  • Programmable Refresh: Refresh the list from outside using a GlobalKey

Examples #

Simple Usage #

Simple Example

Advanced Usage #

Advanced Example

Drag Styles #

Stacked Style #

The default style stacks items neatly behind the dragged item: Stacked Style

Animated Cards #

Provides a modern animated card interface for your dragged items: Animated Cards

Minimalist #

A clean, simple approach with minimal visual elements: Minimalist Style

Changing between styles is simple:

ReorderableMultiDragTheme(
  // Normal theme properties
  draggedItemBorderColor: Colors.blue,
  itemBorderRadius: 8.0,
  // Set the drag style
  dragStyle: DragStyle.animatedCardStyle, // or .stackedStyle, .minimalistStyle
)

Installation #

Add the package to your pubspec.yaml:

dependencies:
  multi_reorderable: ^0.2.0

Then import it in your Dart code:

import 'package:multi_reorderable/multi_reorderable.dart';

Basic Usage #

ReorderableMultiDragList<String>(
  items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'],
  itemBuilder: (context, item, index, isSelected, isDragging) {
    return Container(
      height: 60,
      padding: const EdgeInsets.all(8),
      child: Text(
        item,
        style: TextStyle(
          fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
          color: isDragging ? Colors.grey : Colors.black,
        ),
      ),
    );
  },
  onReorder: (reorderedItems) {
    setState(() {
      items = reorderedItems;
    });
  },
  onSelectionChanged: (selectedItems) {
    print('Selected items: $selectedItems');
  },
  onDone: (selectedItems) {
    print('Done with selection: $selectedItems');
  },
)

Customization #

Theming #

Customize the appearance using the ReorderableMultiDragTheme:

ReorderableMultiDragList<String>(
  // ... other properties
  theme: ReorderableMultiDragTheme(
    itemColor: Colors.white,
    selectedItemColor: Colors.blue.shade50,
    selectionBarColor: Colors.blue.shade100,
    draggedItemBorderColor: Colors.blue,
    itemBorderRadius: 8.0,
    itemHorizontalMargin: 8.0,
    itemVerticalMargin: 4.0,
    maxStackOffset: 6.0,
    maxStackRotation: 3.0,
  ),
)

Custom Builders #

Use builder functions for advanced customization:

ReorderableMultiDragList<String>(
  // ... other properties
  selectionBarBuilder: (context, selectedCount, onDone) {
    return Container(
      padding: const EdgeInsets.all(16),
      color: Colors.blueGrey.shade100,
      child: Row(
        children: [
          Text('$selectedCount items selected'),
          const Spacer(),
          ElevatedButton(
            onPressed: onDone,
            child: const Text('Apply'),
          ),
        ],
      ),
    );
  },
  dragHandleBuilder: (context, isSelected) {
    return Icon(
      Icons.drag_indicator,
      color: isSelected ? Colors.blue : Colors.grey,
    );
  },
)

Additional Options #

ReorderableMultiDragList<String>(
  // ... other properties
  showDoneButton: true,
  doneButtonText: 'Apply',
  showSelectionCount: true,
  selectionCountText: '{} selected',
  itemHeight: 70.0,
  showDividers: true,
  dragAnimationDuration: const Duration(milliseconds: 200),
  reorderAnimationDuration: const Duration(milliseconds: 300),
  autoScrollSpeed: 15.0,
  autoScrollThreshold: 100.0,
  headerWidget: Container(
    padding: const EdgeInsets.all(16),
    child: const Text('My Items', style: TextStyle(fontWeight: FontWeight.bold)),
  ),
  footerWidget: Container(
    padding: const EdgeInsets.all(16),
    child: const Text('Swipe to see more'),
  ),
)

Pagination #

The widget now offers improved pagination with external control to prevent duplicate page loading:

// Create a global key to access the widget's state
final listKey = GlobalKey<ReorderableMultiDragListState<MyItem>>();

// Track your current page in your state
int currentPage = 1;

// In your build method
ReorderableMultiDragList<MyItem>(
  listKey: listKey,
  items: myItems,
  pageSize: 20, // Number of items per page
  currentPage: currentPage, // Pass your current page
  totalPages: totalPages, // Optional - if you know the total number of pages
  onPageRequest: (page, pageSize) async {
    print('Loading page: $page'); 
    
    // Make your API request with the provided page number
    final response = await yourApi.fetchItems(page: page, pageSize: pageSize);
    
    setState(() {
      // Add new items to your list (not replace)
      myItems.addAll(response.items);
      // IMPORTANT: Update your current page to match the loaded page
      currentPage = page;
    });
  },
  // Customize loading indicator (optional)
  loadingWidgetBuilder: (context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const CircularProgressIndicator(),
        const SizedBox(height: 8),
        const Text('Loading more items...'),
      ],
    );
  },
  // Customize "no more items" message (optional)
  noMoreItemsBuilder: (context) {
    return Container(
      padding: const EdgeInsets.all(16),
      child: const Text(
        "You've reached the end of the list",
        style: TextStyle(
          fontStyle: FontStyle.italic,
          color: Colors.grey,
        ),
      ),
    );
  },
  // ... other properties
)

Key Pagination Features:

  1. External page control: The currentPage parameter lets you track and control page loading externally
  2. Prevent duplicate loading: Widget uses the provided currentPage to ensure pages aren't loaded twice
  3. Total pages limit: Optional totalPages parameter to stop pagination at a known limit
  4. Smart empty state: Shows appropriate messages for both loading and "no more items" states
  5. Customizable indicators: Custom builders for both loading indicators and end-of-list messages

Pull-to-Refresh #

Enable pull-to-refresh functionality:

ReorderableMultiDragList<MyItem>(
  // ... other properties
  enablePullToRefresh: true, // Enable pull-to-refresh
  onRefresh: () async {
    // Clear your existing items
    setState(() {
      myItems.clear();
    });
    
    // Fetch fresh data (first page)
    final response = await yourApi.fetchItems(page: 1);
    
    setState(() {
      myItems.addAll(response.items);
    });
  },
  // Customize refresh indicator (optional)
  refreshIndicatorColor: Colors.blue,
  refreshIndicatorBackgroundColor: Colors.white,
  refreshIndicatorDisplacement: 40.0,
)

If you don't provide an onRefresh callback, the widget will automatically use the onPageRequest callback with page 1.

Programmatic Refresh #

Refresh the list from outside using the GlobalKey:

// Refresh the list programmatically
void refreshList() {
  // Reset pagination (optional)
  listKey.currentState?.refreshItems(resetPagination: true);
}

// Use in a button or other event
FloatingActionButton(
  onPressed: refreshList,
  child: Icon(Icons.refresh),
)

Example #

Check out the /example folder for a complete implementation.

About the Developer #

This package is developed and maintained by Abdelrahman Atef, a Flutter developer specializing in creating custom, high-quality UI components and applications.

Work with me

Feel free to reach out for custom development or modifications to this package.

License #

This package is available under the MIT License.

8
likes
0
points
347
downloads

Publisher

verified publishercodesters-inc.com

Weekly Downloads

A Flutter package for multi-selection and animated reordering of items.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on multi_reorderable