example:有一个需求是多个横向滚动的列表纵向排列在一个界面中。
我们直接写,在Column 中直接加上 ListView :
class TextPage extends StatelessWidget {
const TextPage({super.key});
@override
Widget build(BuildContext context) {
return Column(children: [
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return Item();
},
),
],);
}
}
当当当,恭喜你,喜提报错:
vertical space in which to expand.
解决这个问题,我们通常都会在 ListView 外面添加一个SizedBox 来约束ListView。
SizedBox(
height: 100.w,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return Item();
},
),
),
但是! 这这样的写法并不是那么优雅。会在特定情况下出现一出BUG。
当调节手机字体大小的时候,就会导致Item 组件中的字体大小高度发生变化,但是我们约束 ListView 的 SizedBox 的高度是固定的,就会出现溢出报错。
可能会有人说 可以用 IntrinsicHeight 包裹。但是 ListView 是懒加载的。所以 IntrinsicHeight 不能获取所有的Item的高度。如果Item的高度会变化呢。
itemBuilder: (BuildContext context, int index) {
if(index > 10){
return Container(height: 400,width: 200,color: Colors.pink,);
}
return Item();
},
上一张图片中,两个同样的ListView 同样的Item。
为什么下面的 ListView 就会根据Item自适应高度。但是上面的就会溢出报错。
这就是今天要讲的优雅的是向 Column 嵌入横向 ListView。
废话不多说直接上代码:
Stack(
children: [
const IgnorePointer(
child: Opacity(
opacity: 0,
child: Item(),
),
),
const SizedBox(width: double.infinity),
Positioned.fill(
child: ListView.builder(
itemCount: 100,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Item();
},
)),
],
)
解析:
这里用了Stack 的特性。 Stack 的高度会根据 其子组件中 非Positioned组件的最大高度来自撑开的。