Flutter中如何为GridView设置灵活自适应高度
Flutter 无Expanded场景下GridView高度适配异常解决
问题背景
Flutter开发中需要为GridView设置灵活高度,受业务场景限制无法使用Expanded组件,最初选择手动计算尺寸的方式实现,但该方案仅在部分机型运行正常,其余机型适配效果不符合预期,初始实现代码如下:
@override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; final double itemHeight = (size.width / 2) - 64; final double itemWidth = size.width / 2; return Container( color: Colour.backgroundColor, width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 20), margin: const EdgeInsets.only(bottom: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(localized(context, 'photos')!, style: getTitleTextStyle), EmptyLine(height: 14), SizedBox( height: (widget.state!.attachments!.length / 2).round() * (itemWidth - 8), child: GridView.builder( physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 8, crossAxisSpacing: 16), itemCount: widget.state!.attachments!.length, itemBuilder: (context, index) => _buildImageCard(index, context, itemHeight, itemWidth), )), ], ), ); }
问题原因
手动计算GridView容器高度的方案存在固有适配缺陷:
- 计算逻辑没有覆盖GridView的内边距、网格间距实际占用的布局尺寸
- 没有兼容不同设备的屏幕密度、系统安全区、组件默认边距带来的尺寸差
- 手动计算出的高度和
SliverGridDelegateWithFixedCrossAxisCount实际渲染的子组件总高度存在偏差,最终导致部分机型出现内容溢出、上下留白的异常。
解决方案
经测试,给GridView添加shrinkWrap: true属性后,所有机型适配均可正常运行,该方案的实现逻辑是:
shrinkWrap: true属性会让GridView放弃默认的“占用父组件剩余可用空间”的布局逻辑,转而根据自身子组件的总渲染高度来确定自身尺寸,不需要开发者手动计算高度,从根源上避免了手动计算带来的机型适配误差。
调整后的GridView核心代码如下:
GridView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, // 新增该配置即可解决适配问题 gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 8, crossAxisSpacing: 16), itemCount: widget.state!.attachments!.length, itemBuilder: (context, index) => _buildImageCard(index, context, itemHeight, itemWidth), )
注意:使用该方案时搭配NeverScrollableScrollPhysics禁用GridView自身滚动,可避免和父级滚动组件(如ListView、Column所在的可滚动容器)出现滚动冲突。
内容的提问来源于stack exchange,提问作者Lala Naibova
相关产品推荐
相关产品推荐

