106
53

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 3 years have passed since last update.

【Flutter】Columnの中でListViewを使う時にエラーが出る

Last updated at Posted at 2020-04-08

問題

Columnの中でListViewを使う場合、そのまま使うとListViewの大きさが定まらず、下記のようなエラーが吐かれてしまう。

Column(
   mainAxisAlignment: MainAxisAlignment.center,
   children: [
       Text('top text'),
       ListView.builder(
           //shrinkWrap: true が無い
           itemCount: 20,
           itemBuilder: (BuildContext context, int index) {
              return index % 2 == 0 ? Text('item no:$index') : Divider();
           }),
       Text('end text')
       ]
)
I/flutter ( 6072): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 6072): The following assertion was thrown during performResize():
I/flutter ( 6072): Vertical viewport was given unbounded height.
I/flutter ( 6072): Viewports expand in the scrolling direction to fill their container. In this case, a vertical
I/flutter ( 6072): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 6072): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter ( 6072): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter ( 6072): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter ( 6072): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter ( 6072): the height of the viewport to the sum of the heights of its children.

この問題に対処する方法はいくつかある。

対処法

1. shrinkWrap: trueを使う

ListViewに対して shrinkWrap: trueを使う。しかし、このプロパティだけだとListViewの部分をスクロールした場合、下記の図のように限界であることを示すアニメーションが再生されてしまう場合がある。そのため、physics: NeverScrollableScrollPhysics()を付けて無効化する。

ListViewをスクロールしたい場合は、高さの制限を設ける必要があるため、FlexibleLimitedBox, SizedBoxを利用した対処法2, 3を参照

flutter_02.png

結果として、下記のようなコードとなる。

Column(
   mainAxisAlignment: MainAxisAlignment.center,
   children: [
       Text('top text'),
       ListView.builder(
           shrinkWrap: true,   //追加
           physics: const NeverScrollableScrollPhysics(),  //追加
           itemCount: 20,
           itemBuilder: (BuildContext context, int index) {
              return index % 2 == 0 ? Text('item no:$index') : Divider();
           }),
       Text('end text')
       ]
)

2. Flexible, Expandedを使う

Flexibleを用いると、ListViewがOverflowする限界まで広がる
同様にExpandedも使うことができる

下記はFlexibleを利用した例

Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      Text('top text'),
      Flexible(    //Flexibleでラップ
        child: ListView.builder(
              itemCount: 600,
              itemBuilder: (BuildContext context, int index) {
                return index % 2 == 0 ? Text('item no: $index') : Divider();
            }),
      ),
      Text('end text')
])

flexible.gif

3. LimitedBox, SizedBoxを使う

予め、ListViewの最大の大きさを定められる場合はLimitedBoxでListViewをラップする
また、高さを可変ではなく固定したい場合は、SizedBoxでラップする

コードはLimitedBoxを利用した例

Column(
  mainAxisAlignment: MainAxisAlignment.center, 
  children: [
    Text('top text'),
    LimitedBox(
      maxHeight: 300,    //最大の高さを指定
      child: ListView.builder(
        itemCount: 600,
        itemBuilder: (BuildContext context, int index) {
          return index % 2 == 0 ? Text('item no: $index') : Divider();
      })),
    Text('end text'),
  ])

limitedBox.gif

最後に

誤り等ございましたら、ご指摘くださると幸いです

参考文献

How to add a ListView to a Column in Flutter? - Stack Overflow
Flutter: ListView disable scrolling with touchscreen - Stack Overflow

106
53
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
106
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?