Flutter中ListView嵌套Stack+Positioned遇size.isFinite及底部溢出问题
问题原因及解决方法
错误根源:Stack的尺寸依赖逻辑
Stack组件的大小默认由未被Positioned定位的子组件决定。当你给所有子组件都加上top/right这类定位属性后,所有子组件都脱离了Stack的文档流,Stack失去了确定自身尺寸的参考基准,变成无限制的不确定尺寸。
而你使用的ListView.builder设置了shrinkWrap: true,这个属性要求列表每一项必须有明确的尺寸。当Stack尺寸不确定时,就会触发size.isFinite错误;同时因为Stack没有高度限制,内部内容超出可视范围,就会出现“底部溢出102像素”的问题。
当你移除第一个Positioned的top和right属性后,这个子组件成为非定位组件,Stack会以它的尺寸(75.0高度 + width*0.9宽度)作为自身大小,父组件SizedBox和ListView的item也就有了明确尺寸,错误自然消失。
两种修正方案
方案一:给Stack设置明确尺寸
用SizedBox包裹Stack,直接指定宽高,确保即使所有子组件都是Positioned,Stack也有确定大小:ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: HomeProvider().homeItems.length, itemBuilder: (context, index) => SizedBox( // 指定Stack宽高,和内部容器尺寸对应 width: width * 0.9, height: 75.0, child: Stack( children: [ Positioned( top: 35, right: 20, child: Material( child: Container( height: 75.0, width: width * 0.9, decoration: BoxDecoration( color: ColorManager.white, borderRadius: BorderRadius.circular(0.0), boxShadow: [ BoxShadow( color: ColorManager.grey, offset: const Offset(-10.0, 10.0), blurRadius: 20.0, spreadRadius: 4.0, ), ], ), ), ), ), Positioned( top:30, right:45, // ... 其他内容 ), Positioned( top:30, right:45, // ... 其他内容 ), ], ), ), )方案二:保留非定位的基准组件
沿用你当前能正常运行的方式,让第一个子组件不使用Positioned定位,作为Stack的尺寸基准。它本身是背景容器,这样的设计逻辑也更合理,其他Positioned组件基于这个基准容器定位即可。
内容的提问来源于stack exchange,提问作者sunny
相关产品推荐
相关产品推荐

