制作Note

ListViewでスライドすると削除できて並び替えもできるようにしたい|flutter


flutter doctor

ReorderableListViewクラス

まずリストの並び替えとしてReorderableListViewクラスを使用。
リスト内の項目をドラッグ&ドロップ(ロングタップ移動)で並び替えることができます。

onReorderコールバックを使って、リスト内の項目の順番が変更されたときにリストを更新します。

flutter_slidableのインストール

flutter_slidableというパッケージを使用します

右スライドして削除ボタンを表示する為のもの。
「削除」ボタンをタップすると、対応する項目がリストから削除されます。

古いバージョンと記述方法が違うので、いちおう要チェック。

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

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: DragAndDropList(),
    );
  }
}

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

  @override
  State<DragAndDropList> createState() => _DragAndDropListState();
}

class _DragAndDropListState extends State<DragAndDropList> {
  final List<int> _items = List.generate(50, (index) => index + 1);  //50個のリストを作成

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Drag & Drop List'),
      ),
      body: ReorderableListView.builder(
        itemCount: _items.length,
        onReorder: _onReorder,  //リストを長押しして上下に移動できる、下部に記載
        itemBuilder: (context, index) {
          final item = _items[index]; //上記50個のリストを並べる
          return _buildSlidable(item);  //横スライドで削除できるウィジェット
        },
      ),
    );
  }

//横スライドで削除できるウィジェット
  Widget _buildSlidable(int item) {
    return Slidable(
      key: ValueKey(item),
      startActionPane: ActionPane(
      motion: const DrawerMotion(),
      extentRatio: 0.25,
      children: [
        SlidableAction(
          label: '削除',
          backgroundColor: Colors.red,
          icon: Icons.delete,
          onPressed: (context) {
            _removeItem(item);
          },
        ),
      ],
    ),
      child: Container(
        decoration: BoxDecoration(
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.grey.withOpacity(0.5),
              spreadRadius: 2,
              blurRadius: 5,
              offset: const Offset(0, 3),
            ),
          ],
          borderRadius: BorderRadius.circular(10),
        ),
        margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
        padding: const EdgeInsets.all(16),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(
              '$item',
              style: const TextStyle(fontSize: 18),
            ),
            const Icon(
              Icons.drag_handle,
              color: Colors.grey,
            ),
          ],
        ),
      ),
    );
  }

//タップ長押しで上下に移動できる
void _onReorder(int oldIndex, int newIndex) {
    setState(() {
      if (newIndex > oldIndex) {
        newIndex -= 1;
      }
      final int item = _items.removeAt(oldIndex);
      _items.insert(newIndex, item);
    });
  }

//右スライドした時に削除する
  void _removeItem(int item) {
    setState(() {
      _items.remove(item);
    });
  }
}

※ChatGPTで作成して適宜補正したコードです