📦

[Flutter] ReorderableListViewで一部を並び替えられないようにする

2023/10/21に公開

はじめに

Flutterでリストの並び替えを可能にするReorderableListView
を使っていて、一部を並び替えられないようにしたいケースに遭遇した際の記録です。

イメージしやすいよう具体例を提示すると、以下のようなケースなどで使える内容かと思います。

  • TODOリストで未完了のTODOは並び替えられるようにしたいけど、完了済のTODOは並び替えられないようにしたい

方針

プロパティとして、footerというのが用意されているのでそれを使うだけでした。

https://api.flutter.dev/flutter/material/ReorderableListView/footer.html

A non-reorderable footer item to show after the items of the list.
If null, no footer will appear after the list.

まさにですね。

コード例

せっかくなので(?)、コード例を載せて終わろうと思います。
※ ReorderableListViewのドキュメントに記載のあるサンプルコードに手を入れて、強引に動かしているので一部違和感のある箇所ありますが、本記事の本質ではないのでご理解いただけると幸いです..。

import 'package:flutter/material.dart';

/// Flutter code sample for [ReorderableListView].

void main() => runApp(const ReorderableApp());

class ReorderableApp extends StatelessWidget {
  const ReorderableApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('ReorderableListView Sample')),
        body: const ReorderableExample(),
      ),
    );
  }
}

class ReorderableExample extends StatefulWidget {
  const ReorderableExample({super.key});

  
  State<ReorderableExample> createState() => _ReorderableListViewExampleState();
}

class _ReorderableListViewExampleState extends State<ReorderableExample> {
  final List<int> _items = List<int>.generate(3, (int index) => index);
  final List<int> _notReorderItems =
      List<int>.generate(8, (int index) => index);

  
  Widget build(BuildContext context) {
    final ColorScheme colorScheme = Theme.of(context).colorScheme;
    final Color oddItemColor = colorScheme.primary.withOpacity(0.05);
    final Color evenItemColor = colorScheme.primary.withOpacity(0.15);

    return ReorderableListView(
      padding: const EdgeInsets.symmetric(horizontal: 40),
      onReorder: (int oldIndex, int newIndex) {
        setState(() {
          if (oldIndex < newIndex) {
            newIndex -= 1;
          }
          final int item = _items.removeAt(oldIndex);
          _items.insert(newIndex, item);
        });
      },
      footer: ListView(
        shrinkWrap: true,
        children: <Widget>[
          for (int index = 3; index < _notReorderItems.length; index += 1)
            ListTile(
              key: Key('$index'),
              tileColor:
                  _notReorderItems[index].isOdd ? oddItemColor : evenItemColor,
              title: Text('Item ${_notReorderItems[index]}'),
            ),
        ],
      ),
      children: <Widget>[
        for (int index = 0; index < _items.length; index += 1)
          ListTile(
            key: Key('$index'),
            tileColor: _items[index].isOdd ? oddItemColor : evenItemColor,
            title: Text('Item ${_items[index]}'),
          ),
      ],
    );
  }
}

ほとんどがサンプルコードのままで、追加したのはfooterの箇所くらいです。

動かすと以下のようになります。

indexが0,1,2のアイテムは並び替えできるものの、3以降のアイテム(コード上では_notReorderItems)は並び替えられないことが確認できます。

おわりに

「一般的に考えうる実現したいこと」は用意されていることが多々あるので、
ドキュメントをしっかり読んで、車輪の再発明をしないようにしていきたいものです。

Discussion