問題
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をスクロールしたい場合は、高さの制限を設ける必要があるため、Flexible
やLimitedBox, SizedBox
を利用した対処法2, 3を参照
結果として、下記のようなコードとなる。
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')
])
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'),
])
最後に
誤り等ございましたら、ご指摘くださると幸いです
参考文献
How to add a ListView to a Column in Flutter? - Stack Overflow
Flutter: ListView disable scrolling with touchscreen - Stack Overflow