3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Posted at

はじめに

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

この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

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

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

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

══╡ 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というのはなんと存在しません!!
じゃどうやって背景色つけたり角を丸くしたりするの???となる訳です。。。

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

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

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

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

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

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?