Flutter中GridView.count组件水平滚动不生效如何解决
问题原因
滚动无法生效的核心错误是你为滚动组件设置了physics: const NeverScrollableScrollPhysics(),这个属性的作用就是完全禁用组件的滚动响应,无论你替换成ListView还是调整其他参数,只要保留这个配置,组件就不会响应任何滚动手势。
除此之外你的实现还有几个冗余/错误点:
- 用
GridView.count实现单排横向列表属于场景错配,这类场景用ListView实现更简洁,性能更好 - 父容器已经设置了固定高度的前提下,给滚动组件加
shrinkWrap: true属于多余配置,会额外增加性能开销 - 水平滚动场景下你没有给列表子项设置明确宽度,容易触发布局约束异常
- 原代码没有做
FutureBuilder的空数据判断,数据未加载完成时直接取snapshot.data会触发空指针报错
修复方案
- 移除禁止滚动的physics配置,如果需要内容不足一屏时也能触发滚动回弹效果,可将physics替换为
const AlwaysScrollableScrollPhysics(),不需要特殊效果的话直接省略physics参数使用系统默认配置即可。 - 将
GridView.count替换为ListView实现横向单排列表,给每个卡片项设置固定宽度避免布局报错。 - 补充数据加载状态判断,避免空指针异常。
修正后的可运行代码
@override Widget build(BuildContext context) { SizeConfig().init(context); return Expanded( child: Column( children: [ Padding( padding: EdgeInsets.symmetric( vertical: SizeConfig.blockSizeVertical * 2), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Names', style: Theme.of(context).textTheme.headline6, ), InkWell( onTap: () {}, child: Row(children: [ Text('show more', style: Theme.of(context).textTheme.caption), const Padding( padding: EdgeInsets.only(top: 2), child: Icon( Icons.keyboard_arrow_left_sharp, size: 20, ), ), ]), ), ], ), ), FutureBuilder<DataModel>( future: InfoAPI('assets/itemsData.json').getDataLocally(context), builder: (context, snapshot) { // 数据未加载完成时显示加载态 if (!snapshot.hasData) { return SizedBox( height: SizeConfig.blockSizeVertical * 20, child: const Center(child: CircularProgressIndicator()) ); } final data = snapshot.data; final List<String> list = getnames(data); return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: Theme.of(context).primaryColor, ), height: SizeConfig.blockSizeVertical * 20, // 横向滚动列表直接用ListView实现 child: ListView.separated( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric( vertical: 8.0, horizontal: 10.0), physics: const AlwaysScrollableScrollPhysics(), itemCount: list.length, // 配置卡片之间的横向间距 separatorBuilder: (context, index) => const SizedBox(width: 12), itemBuilder: (context, index) { return SizedBox( // 给每个卡片设置固定宽度,适配横向滚动布局 width: SizeConfig.blockSizeVertical * 16, child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16)), color: Theme.of(context).cardColor, child: Center( child: Text( list[index], style: Theme.of(context).textTheme.bodyText1, ))), ); }, ), ); }) ], ), ); }
你可以根据自己的UI需求调整卡片宽度、间距、圆角等参数,不影响滚动逻辑。
内容的提问来源于stack exchange,提问作者Bushra
相关产品推荐
相关产品推荐

