Flutter sliverの中でContainerを使う A RenderRepaintBoundary expected a child of type RenderBox but received a child of type RenderSliverList.

# はじめに
いい感じのスクロール画面を作ろうとした時に大体使うであろう`sliver`系のウィジェット。
代表的なのはSliverAppBar

https://api.flutter.dev/flutter/material/SliverAppBar-class.html


このsliverの中でContainerを使いたい場面は多々あるかと。
例えば`SliverList`に背景色をつけようとしたり。

が、、、**sliverに対してはsliverしか使えない**という原則によって、めちゃ困惑しました。。。

# sliverとは
Sliver（細長い小片）とはスクロール可動領域の一部分を細かくカスタマイズできるウィジェット群です。
Sliverとつくウィジェットは複数あり、普通のウィジェットとは異なるようです。

### Child（普通のウィジェット）ウィジェット:
Childウィジェットは通常のウィジェットです。Container、Text、Image、Row、Columnなどの一般的なウィジェットがこれに該当します。
通常のウィジェットツリーの中で使います。例えば、画面の一部分を作成するためにChildウィジェットを使うことがあります。

### Sliver（スリバー）ウィジェット:
Sliverウィジェットは、スクロール可能なリストやCustomScrollView内で使用される特別なウィジェットです。
一般的に、CustomScrollView内でスクロール可能な要素を作成するために使用されます。これにはSliverAppBar、SliverList、SliverGridなどが含まれます。

この理解はsliverを扱う上で非常に重要です！:neutral_face:


# SliverListに背景色をつけたい
仮に👇のように画面全体ではなく各Listごとに装飾をしたいとします。
![Screenshot 2023-10-19 at 18.41.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/a08749ed-cd14-ee08-5c96-277857be8da6.png)

普通に考えるとこんなコードになります。

```dart
      child: Scaffold(
        body: const CustomScrollView(
          slivers: [
            _SliverAppBar(),
             Container(
              // decorationで装飾
              child: _SliverList(),
            ),
             Container(
              // decorationで装飾
              child: _SliverList(),
            ),
          ],
        ),
      ),
```

しかしこれだとだめなんです。。。
なぜなら`slivers`にはsliver系ウィジェットしか使えないから！


```console
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building Expanded(flex: 1):
A RenderRepaintBoundary expected a child of type RenderBox but received a child of type
RenderSliverList.
RenderObjects expect specific types of children because they coordinate with their children during
layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a
RenderSliver does not understand the RenderBox layout protocol.

The RenderRepaintBoundary that expected a RenderBox child was created by:
  RepaintBoundary ← IndexedSemantics ← _SelectionKeepAlive ←
  NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← KeyedSubtree ←
  SliverList ← _SliverList ← SliverPadding ← Viewport ← IgnorePointer-[GlobalKey#c987a] ← ⋯

The RenderSliverList that did not match the expected child type was created by:
  SliverList ← Expanded ← RepaintBoundary ← IndexedSemantics ← _SelectionKeepAlive ←
  NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← KeyedSubtree ←
  SliverList ← _SliverList ← SliverPadding ← ⋯
```

こんな感じでエラーになります:sob:

>RenderSliver does not understand the RenderBox layout protocol.

要は`sliver`の中で普通のウィジェットは使えない、ということを言われてます

`SliverPadding`はありますが`SliverContainer`というのはなんと存在しません！！
じゃどうやって背景色つけたり角を丸くしたりするの？？？となる訳です。。。

https://api.flutter.dev/flutter/widgets/SliverPadding-class.html

# sliverの中でContainerを再現するにはこれだ！

`DecoratedSliver`なるものがいつの間にやら誕生してました！！:sunglasses:

https://api.flutter.dev/flutter/widgets/DecoratedSliver-class.html

これを使うことでContainerと同じようなことができます。


```dart
      child: Scaffold(
        body: const CustomScrollView(
          slivers: [
            _SliverAppBar(),
             DecoratedSliver(
              // decorationで装飾
              sliver: _SliverList(),
            ),
             DecoratedSliver(
              // decorationで装飾
              sliver: _SliverList(),
            ),
          ],
        ),
      ),
```

sliverの中ではExpandedも使えないので、なかなか扱いがわかってくるまで大変です


# 参考

https://zenn.dev/zudah228/articles/861801143a5d64