[Flutter] DismissibleとReorderableListViewの同時使用に関するエラーの解決

数宇を開発中に、リストの項目をドラッグして並べ替える機能と、項目を横にスワイプして削除する機能を同時に実装する必要がありました。

そのため、ReorderableListViewとDismissibleを同時に使用することができると思われるので、それを試してみました。

Flutter APIマテリアルライブラリに記載されている方法で実装してみました。

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

しかし、リストの最後の項目を削除する場合には問題はありませんでしたが、中間の項目を削除する場合に問題が発生しました。

A dismissed Dismissible widget is still part of the tree.
Make sure to implement the onDismissed handler and to immediately remove the Dismissible widget from the application once that handler has fired.

一瞥した限りでは、削除した項目がまだ残っているようです。

Stack Overflowで検索してみたところ、中間の項目を削除してもリスト内の中間のインデックスが常に残っているため、同じキーを持つウィジェットが続けて残っていると判断されるようです。

そこで提案される解決策は、UniqueKey()をキー値として渡すことです。

それを試してみました。

ReorderableListView (
 ...
 children: <Widget>[
  for (int index = 0; index < _items.length; index += 1)
   Dismissible(
    key: UniqueKey(),
    ...
   ),
 ],
 ...
);

ああ、そうすると削除はうまくいきます。

しかし、私は順序も変更できる必要がありますが、上に移動させると項目がリストの間に入るアニメーションが発生しません...

おそらく、移動中にウィジェットが新しく作成され、キー値が変更されてしまう結果が生じているようです。

最終的に、各データを持つアイテムごとに一意のキーを生成して割り当てる方法で問題を解決しました。

ReorderableListView (
 ...
 children: <Widget>[
 for (int index = 0; index < _items.length; index += 1)
  Dismissible(
   key: _items[index].key,
   ...
  ),
 ],
 ...
);
class Item {
...
Key key = UniqueKey();
...
}


これでうまく動作します!

独自の便利な消費税計算機をお探しの場合は、Google Playストアで数宇をお試しください!


この記事が気に入ったらサポートをしてみませんか?