ColumnやRowで要素ごとに余白を設けたい時使える技

## はじめに
Columnで3個程度同じWidgetを並べる時、Widget間に余白を設けたい場合があります。ListView.separetedのseparatorをColumnでも使いたいみたいな話です。
今回はこういった場合に使える技をいくつか紹介します。

## intersperseパッケージを使う
intersperseパッケージを使うとIterableやListの要素の間に要素を挟めます。

https://pub.dev/packages/intersperse

https://github.com/modulovalue/dart_intersperse

以下はReadmeの引用です。
intersperseは要素の間だけ、intersperseOuterは最初と最後にも要素が挟まれてます。
```dart
    final list1 = intersperse(2, <int>[]); // [];
    final list2 = intersperse(2, [0]); // [0];
    final list3 = intersperse(2, [0, 0]); // [0, 2, 0];
    final list1Outer = intersperseOuter(2, <int>[]); // [];
    final list2Outer = intersperseOuter(2, [0]); // [2, 0, 2];
    final list3Outer = intersperseOuter(2, [0, 0]); // [2, 0, 2, 0, 2];
```
拡張関数も用意されており、以下のようにもできます。（こちらも引用）
```dart
    final list1 = <int>[].intersperse(2); // [];
    final list2 = [0].intersperse(2); // [0];
    final list3 = [0, 0].intersperse(2); // [0, 2, 0];
    final list1Outer = <int>[].intersperseOuter(2); // [];
    final list2Outer = [0].intersperseOuter(2); // [2, 0, 2];
    final list3Outer = [0, 0].intersperseOuter(2); // [2, 0, 2, 0, 2];
```

### 実際に使う
以下のようなWidgetがあったときして
```dart
class Sample extends StatelessWidget {
  const Sample({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    final list = [1, 2, 3];

    return Column(
      children: list
          .map(
            (e) => Text(e.toString()),
          )
          .toList(),
    );
  }
}
```

以下のようにすれば余白を追加できます。
```dart
class Sample extends StatelessWidget {
  const Sample({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    final list = [1, 2, 3];

    return Column(
      children: list
          .map<Widget>(
            (e) => Text(e.toString()),
          )
          .intersperse(
            const SizedBox(
              height: 16,
            ),
          )
          .toList(),
    );
  }
}
```


## intersperseのような関数を独自に定義する
intersperseを使いたくないときは、Iterable<T>やList<T>の拡張関数を用意することもできます。
以下のような感じですね。使い方は同じです。
```dart
extension ListInsertionExtension<T> on List<T> {
  /// 各要素の間に[value]を挿入します。
  List<T> insertBetween(T value) {
    if (this.isEmpty) return [];

    List<T> result = [];
    for (int i = 0; i < this.length; i++) {
      if (i > 0) {
        result.add(value);
      }
      result.add(this[i]);
    }
    return result;
  }
}
```

## gapパッケージもおすすめ
これまでのサンプルコードで余白を設ける時にSizedBoxをもちいましたが、余白を設ける際はgapというパッケージが使いやすいのでおすすめです。

https://pub.dev/packages/gap

Gapウィジェットを使うとColumnの中にあるのかRowの中にあるのかを意識せず余白を設けることができます。
```dart
class Sample extends StatelessWidget {
  const Sample({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    final list = [1, 2, 3];

    return Column(
      children: list
          .map<Widget>(
            (e) => Text(e.toString()),
          )
          .intersperse(
            const Gap(16),
          )
          .toList(),
    );
  }
}
```

## まとめ
ColumnやRowの要素間に余白を設けるときに使える技を紹介しました。


### 余談
intersperseパッケージの最終更新が古いのが気になるという人もいるかもですが、シンプルな機能のパッケージなので更新の余地が無いだけかと思います🙆‍♂️
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2542067/336ec1e5-24ff-ee77-7551-cfe7839dd535.png)

### 余談２
dartにこういった機能がほしいというIssueがありますが、望みは薄そうです👀

https://github.com/dart-lang/sdk/issues/49900