【Flutter】リストの作り方まとめ

# 概要


Flutterでのいろいろなリストの作り方まとめ

# 普通のリスト


「ListVIew.builder」を使用する

```dart
class NormalListScreen extends StatelessWidget {
  const NormalListScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
    return ListView.builder(
        itemCount: _data.length,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Text(_data[index]),
          );
        });
  }
}
```

# 区切り線付きのリスト



「ListView.separated」を使用する

```dart
class SeparatedListScreen extends StatelessWidget {
  const SeparatedListScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
    return ListView.separated(
        itemCount: _data.length,
        separatorBuilder: (BuildContext context, int index) {
          return const Divider(
            color: Colors.grey,
            indent: 10,
            endIndent: 10,
          );
        },
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Text(_data[index]),
          );
        });
  }
}
```

# スワイプで削除できるリスト


「Dismissible」ウィジェットを使用する

```dart
class DismissibleListScreen extends StatelessWidget {
  const DismissibleListScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];
    return ListView.builder(
        itemCount: _data.length,
        itemBuilder: (BuildContext context, int index) {
          return Dismissible(
            key: Key(_data[index]),
            background: Container(
              color: Colors.red,
            ),
            confirmDismiss: (direction) async {
              // 削除の確認
              // falseの場合削除できない
              return true;
            },
            onDismissed: (direction) {
              // 削除が完了し、リサイズ終了時に呼ばれる
            },
            child: ListTile(
              title: Text(_data[index]),
            ),
          );
        });
  }
}
```

# アニメーション付きリスト



「AnimatedList」を使用する

```dart
class SizeAnimatedListScreen extends StatefulWidget {
  const SizeAnimatedListScreen({Key? key}) : super(key: key);

  @override
  State<SizeAnimatedListScreen> createState() => SizeAnimatedListScreenState();
}

class SizeAnimatedListScreenState extends State<SizeAnimatedListScreen> {
  final GlobalKey<AnimatedListState> _listKey = GlobalKey();
  final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];

  @override
  Widget build(BuildContext context) {
    return AnimatedList(
      key: _listKey,
      initialItemCount: _data.length,
      itemBuilder: (context, index, animation) {
        return _buildItem(_data[index], animation);
      },
    );
  }

  Widget _buildItem(String item, Animation<double> animation) {
    return SizeTransition(
      sizeFactor: animation,
      child: ListTile(
        title: Text(item),
        onTap: () {
          int insertIndex = _data.length;
          _data.add('data' + (insertIndex + 1).toString());
          _listKey.currentState?.insertItem(insertIndex,
              duration: const Duration(milliseconds: 100));
        },
        onLongPress: () {
          int removeIndex = _data.indexOf(item);
          _data.removeAt(removeIndex);

          _listKey.currentState?.removeItem(removeIndex, (context, animation) {
            return _buildItem(item, animation);
          }, duration: const Duration(milliseconds: 100));
        },
      ),
    );
  }
}
```

スライド動作させる場合は↓

```dart
class SlideAnimatedListScreen extends StatefulWidget {
  const SlideAnimatedListScreen({Key? key}) : super(key: key);

  @override
  State<SlideAnimatedListScreen> createState() =>
      SlideAnimatedListScreenState();
}

class SlideAnimatedListScreenState extends State<SlideAnimatedListScreen> {
  final GlobalKey<AnimatedListState> _listKey = GlobalKey();
  final _data = ['data1', 'data2', 'data3', 'data4', 'data5'];

  @override
  Widget build(BuildContext context) {
    return AnimatedList(
      key: _listKey,
      initialItemCount: _data.length,
      itemBuilder: (context, index, animation) {
        return _buildItem(_data[index], animation);
      },
    );
  }

  Widget _buildItem(String item, Animation<double> animation) {
    return SlideTransition(
      position: animation.drive(
          Tween<Offset>(begin: const Offset(1.0, 0), end: Offset.zero)
              .chain(CurveTween(curve: Curves.bounceInOut))),
      child: ListTile(
        title: Text(item),
        onTap: () {
          int insertIndex = _data.length;
          _data.add('data' + (insertIndex + 1).toString());
          _listKey.currentState?.insertItem(insertIndex,
              duration: const Duration(milliseconds: 200));
        },
        onLongPress: () {
          int removeIndex = _data.indexOf(item);
          _data.removeAt(removeIndex);

          _listKey.currentState?.removeItem(removeIndex, (context, animation) {
            return _buildItem(item, animation);
          }, duration: const Duration(milliseconds: 200));
        },
      ),
    );
  }
}
```