Working with ReorderableListView in Flutter

Last updated on March 16, 2021 Guest Contributor Loading... Post a comment

ReorderableListView is a built-in widget of Flutter which can help us create list views with the items that can be repositioned and reordered by dragging and dropping.

This article will cover the most important things about the ReorderableListView widget and walks you through 2 complete examples of using it in Flutter applications.

What is the point?

1. There are 2 constructors can be used to implement reorderable lists.

Using the ReorderableListView.builder constructor is suitable when your list has a large number of items (usually loaded from APIs or from a database like SQLite). This has three important parameters:

  • itemCount: The number of items in the list
  • itemBuilder: A function to build list item widgets
  • reOrder: A callback function used by the list to report that a list item has been dragged to a new location in the list and the application should update the order of the items.

Using the ReorderableListView constructor is convenient when your list has a small number of items. The main parameters are:

  • children: A list of widgets.
  • reOrder: A callback function used by the list to report that a list item has been dragged to a new location in the list and the application should update the order of the items.

2. In general, ReorderableListView goes with a stateful widget. The reorder functions are almost the same in many cases:

onReorder: (oldIndex, newIndex) {
            setState(() {
              if (newIndex > oldIndex) {
                newIndex = newIndex - 1;
              }
              final item = _myListData.removeAt(oldIndex);
              _myListData.insert(newIndex, element);
            });
}

// Don't forget to change _myListData with your own list 

3. Each item of a ReorderableListView must have a key in order to distinguish the list items after their position is changed. Using ValueKey() is fine. If the keys are missing, a major error will occur.

Examples

ReorderableListView.builder

Preview

This sample app contains a ReorderableListView that holds one hundred fiction products. Each product in this list can be moved to a new location started by a long press gesture then dragging and dropping.

The code

// main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Remove the debug banner
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // Generate dummy data for the list view
  List<String> _products =
      List.generate(100, (index) => "Product ${index.toString()}");

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Kindacode.com'),
      ),
      body: ReorderableListView.builder(
          itemCount: _products.length,
          itemBuilder: (context, index) {
            final String productName = _products[index];
            return Card(
              key: ValueKey(productName),
              color: Colors.amberAccent,
              elevation: 1,
              margin: const EdgeInsets.all(10),
              child: ListTile(
                contentPadding: EdgeInsets.all(25),
                title: Text(
                  productName,
                  style: TextStyle(fontSize: 18),
                ),
                trailing: Icon(Icons.drag_handle),
                onTap: () {/* Do something else */},
              ),
            );
          },
          // The reorder function
          onReorder: (oldIndex, newIndex) {
            setState(() {
              if (newIndex > oldIndex) {
                newIndex = newIndex - 1;
              }
              final element = _products.removeAt(oldIndex);
              _products.insert(newIndex, element);
            });
          }),
    );
  }
}

ReorderableListView

Preview

This example demonstrates a very common case in real life: a task app allows the user to change the priority of to-do tasks.

The code

// main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Remove the debug banner
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      // home: HomePage(),
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // This variable holds the list's items
  List<String> _todos = ['Task A', 'Task B', 'Task C', 'Task D'];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Kindacode.com'),
      ),
      body: ReorderableListView(
          header: Container(
              padding: const EdgeInsets.all(25),
              color: Colors.amber,
              child: const Text('My Todo List')),
          children: _todos
              .map((task) => Container(
                    key: ValueKey(task),
                    decoration: BoxDecoration(
                        color: Colors.greenAccent,
                        border: Border.all(width: 1, color: Colors.green)),
                    child: ListTile(
                      contentPadding: EdgeInsets.all(25),
                      leading: Icon(Icons.lock_clock),
                      title: Text(
                        task,
                        style: TextStyle(fontSize: 24),
                      ),
                      trailing: Icon(Icons.drag_handle_outlined),
                    ),
                  ))
              .toList(),
          // The reorder function
          onReorder: (oldIndex, newIndex) {
            setState(() {
              if (newIndex > oldIndex) {
                newIndex -= 1;
              }
              final element = _todos.removeAt(oldIndex);
              _todos.insert(newIndex, element);
            });
          }),
    );
  }
}

Conclusion

We have gone over the fundamentals of the ReorderableListView widget and seen 2 examples of using it. If you would like to learn more interesting and new things about Flutter, take a look at the following articles: Example of sortable DataTable in Flutter, 4 Ways to Store Data Offline in Flutter, Flutter: Check Internet Connection without any plugins, How to make an image carousel in Flutter.

You can also check out our Flutter category page or Dart category page for the latest tutorials and examples.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Related Articles