How to use ReorderableListView

The ReorderableListView widget is another good example of Scrolling widgets, which we’ve covering in a great detail.

As the name suggests, it’s a kind of ListView of items where the user can reorder the items by dragging one item over another.

However, this flutter widget is ideal for small items.

Why?

Because initially the ReorderableListView widget has a children parameter that returns a list of items where each item gets involved when the dragging takes place.

In other words, when the list is constructed it requires doing work for every child; not only those children, which are visible.

In addition, all list items must have a key that is not null.

Let us create a list of numerical items and order them from 1 to 10.

After all, the ReorderableListView‘s children parameter will return a list that can be scrolled to the end.

To understand the concept let’s see the screenshots one after another. After that we’ll see the full code and discuss how things take place.

ReorderableListView first instance
ReorderableListView first instance

In our code, we have a list of 10 numerical items that are in perfect order.

As a result, the first screenshot displays the number in order, starting from 1 and the incremental expansion of numbers move downwards.

Now, let’s try to reorder the number.

ReorderableListView second instance where item is being dragged
ReorderableListView second instance where item is being dragged

We can see that the number 10 is being dragged and we’re trying to lace it over the number 8.

ReorderableListView third instance where item 10 is placed over item 8
ReorderableListView third instance where item 10 is placed over item 8

We’ve successfully dragged and placed 10 over 8.

Let’s come back to the topic we were talking about. How this reordering takes place?

Let’s see the full code first.

import 'package:flutter/material.dart';

/// This is the main application widget.
class ReorderableListViewSample extends StatelessWidget {
  const ReorderableListViewSample({Key? key}) : super(key: key);

  static const String _title = 'ReorderableListView Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const ReorderableListViewHome(),
      ),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class ReorderableListViewHome extends StatefulWidget {
  const ReorderableListViewHome({Key? key}) : super(key: key);

  @override
  State<ReorderableListViewHome> createState() =>
      _ReorderableListViewHomeState();
}

class _ReorderableListViewHomeState extends State<ReorderableListViewHome> {
  /// generating 10 items
  final List<int> _items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  @override
  Widget build(BuildContext context) {
    return ReorderableListView(
      padding: const EdgeInsets.symmetric(horizontal: 40),
      children: _items
          .map(
            (e) => Container(
              key: ValueKey(e),
              decoration: BoxDecoration(
                color: Colors.blue,
                border: Border.all(
                  color: Colors.red,
                  width: 2.0,
                  style: BorderStyle.solid,
                ),
                borderRadius: const BorderRadius.all(Radius.circular(40.0)),
                boxShadow: const [
                  BoxShadow(
                    color: Colors.black54,
                    blurRadius: 20.0,
                    spreadRadius: 20.0,
                  ),
                ],
                gradient: const LinearGradient(
                  begin: Alignment.centerLeft,
                  end: Alignment.centerRight,
                  colors: [
                    Colors.red,
                    Colors.white,
                  ],
                ),
              ),
              child: ListTile(
                contentPadding: const EdgeInsets.all(25),
                leading: const Icon(Icons.input_outlined),
                title: Text(
                  '$e',
                  key: ValueKey(e),
                  style: const TextStyle(
                    color: Colors.black,
                    fontSize: 80.0,
                    fontFamily: 'Allison',
                    fontWeight: FontWeight.bold,
                  ),
                ),
                trailing: const Icon(Icons.drag_indicator_outlined),
              ),
            ),
          )
          .toList(),
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          if (oldIndex < newIndex) {
            newIndex -= 1;
          }
          final int item = _items.removeAt(oldIndex);
          _items.insert(newIndex, item);
        });
      },
    );
  }
}

The first thing first, so we have a list of items.

/// generating 10 items
  final List<int> _items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

Nothing special in this. As we have wanted to arrange the numbers in order, we’ve declared a list of numerical items where numbers are arranged in order.

Next we’ve taken necessary steps so that the ReorderableListView‘s children parameter will return this list. As flutter follows the declarative style of programming, we don’t have to run for loop manually. On the contrary, flutter maps that list and gives us an output that can be displayed using layout widgets.

Therefore we’ve decorated the list using the decoration parameter of the Container widget. And as a child parameter we pass a ListTile.

_items
          .map(
            (e) => Container(
              key: ValueKey(e),
              decoration: BoxDecoration(
                color: Colors.blue,
                border: Border.all(
                  color: Colors.red,
                  width: 2.0,
                  style: BorderStyle.solid,
                ),
                borderRadius: const BorderRadius.all(Radius.circular(40.0)),
                boxShadow: const [
                  BoxShadow(
                    color: Colors.black54,
                    blurRadius: 20.0,
                    spreadRadius: 20.0,
                  ),
                ],
                gradient: const LinearGradient(
                  begin: Alignment.centerLeft,
                  end: Alignment.centerRight,
                  colors: [
                    Colors.red,
                    Colors.white,
                  ],
                ),
              ),
              child: ListTile(
                contentPadding: const EdgeInsets.all(25),
                leading: const Icon(Icons.input_outlined),
                title: Text(
                  '$e',
                  key: ValueKey(e),
                  style: const TextStyle(
                    color: Colors.black,
                    fontSize: 80.0,
                    fontFamily: 'Allison',
                    fontWeight: FontWeight.bold,
                  ),
                ),
                trailing: const Icon(Icons.drag_indicator_outlined),
              ),
            ),
          )
          .toList(),

However, most importantly, we need to handle two things to make things happen.

Granted we cannot think of ReorderableListView widget as a magical widget, but we need to understand the logic behind it.

Firstly, we need to provide key to each item of the list.

Container(
              key: ValueKey(e),
...
title: Text(
                  '$e',
                  key: ValueKey(e),
....

Secondly, we need a callback by the list to report that a list item has been dragged to a new position in the list. The ancestor StatefulWidget then updates the order of the item.

onReorder: (int oldIndex, int newIndex) {
        setState(() {
          if (oldIndex < newIndex) {
            newIndex -= 1;
          }
          final int item = _items.removeAt(oldIndex);
          _items.insert(newIndex, item);
        });
      },

On the whole, now it makes sense. And lastly we achieve almost a kind of magical aura where we can drag any item on the screen and reorder them as we wish.

For more such wonderful UI widgets you may visit the GitHub repository.

By the way, you may want to take a look at the other Scrolling Widgets, before we close down further reading on this topic. We have a list below.

What is ListView Flutter? How do I use ListView in Flutter?

How do I use SingleChildScrollView in flutter?

What is GridView and how do you centre a GridView item in Flutter?

What is GridView builder in Flutter?

What is the grid view in Flutter?

What is GridView count in flutter?

What is GridView.extent in Flutter?

How do I make my collapsing toolbar flutter?

What is SliverGrid in flutter?

How to use CustomScrollView in Flutter?

How to use NestedScrollView in flutter?

How to use PageView in Flutter

What is PageView builder in flutter?

What is PageView custom in flutter?

How to use DraggableScrollableSheet

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

7 responses to “How to use ReorderableListView”

  1. […] our previous section we’ve seen how we can rearrange list in Flutter. Yes, we are talking off ReorderableListView widget. By the way, we can also rearrange list in flutter using […]

  2. […] How to use ReorderableListView […]

  3. […] How to use ReorderableListView […]

  4. […] How to use ReorderableListView […]

  5. […] our previous section we’ve seen how we can rearrange list in Flutter. Yes, we are talking off ReorderableListView widget. By the way, we can also rearrange list in flutter using […]

  6. […] How to use ReorderableListView […]

  7. […] How to use ReorderableListView […]

Leave a Reply