如何让GridView子项高度自适应其中最高子项的高度?
解决GridView子项高度自适应最高子项的问题
原生GridView的SliverGridDelegateWithFixedCrossAxisCount不支持自动让所有子项高度统一为最高子项的高度,以下是两种可行的解决方案:
方法一:手动计算最大子项高度
通过先布局子项获取高度,再将最大高度设置为mainAxisExtent,实现统一高度:
- 定义变量存储最大高度和子项的全局Key:
double _maxItemHeight = 0; List<GlobalKey> _itemKeys = [];
- 初始化阶段生成Key并延迟计算最大高度:
@override void initState() { super.initState(); _itemKeys = List.generate(prizes.length, (index) => GlobalKey()); // 等待首次布局完成后计算高度 WidgetsBinding.instance.addPostFrameCallback((_) { _calculateMaxHeight(); }); } void _calculateMaxHeight() { double maxHeight = 0; for (var key in _itemKeys) { final renderBox = key.currentContext?.findRenderObject() as RenderBox?; if (renderBox != null) { final height = renderBox.size.height; if (height > maxHeight) { maxHeight = height; } } } setState(() { _maxItemHeight = maxHeight; }); }
- 修改GridView代码,绑定Key并使用计算出的最大高度:
GridView.builder( shrinkWrap: true, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisExtent: _maxItemHeight, // 用计算出的最大高度替代固定值 crossAxisSpacing: 8, mainAxisSpacing: 8, ), itemCount: prizes.length, itemBuilder: (context, index){ return Card( key: _itemKeys[index], // 绑定全局Key用于获取高度 elevation: 3.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0)), color: Colors.white, child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Stack( children: [ Image.asset(prizes[index]["image"]), ], ), Padding( padding: const EdgeInsets.only(top: 10.0), child: Text( prizes[index]["name"], style: const TextStyle(fontWeight: FontWeight.bold), ), ), Padding( padding: const EdgeInsets.only(top: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( prizes[index]["cost"].toString(), style: const TextStyle(fontWeight: FontWeight.normal), ), Padding( padding: const EdgeInsets.only(left : 4.0), child: SizedBox( width: 14, height: 14, child: svg), ), ], ), ), Padding( padding: const EdgeInsets.only(top: 10), child: ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.blue), shape: MaterialStateProperty.all<RoundedRectangleBorder>( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ) ) ), onPressed: () async {}, child: Padding( padding: EdgeInsets.all(15.0), child: Text(AppLocalizations.of(context)!.riscuoti, style: TextStyle( fontSize: 16 ), ), ), ), ), ], ), ), ); }, )
注意:这种方法会有首次布局后高度调整的闪烁,适合数据量不大的场景。
方法二:使用第三方库实现自适应高度网格
借助flutter_staggered_grid_view库,可以更简洁地实现同一行子项高度统一:
- 添加依赖到
pubspec.yaml:
dependencies: flutter_staggered_grid_view: ^0.7.0
- 替换原生GridView为
StaggeredGridView.count:
StaggeredGridView.count( shrinkWrap: true, crossAxisCount: 2, mainAxisSpacing: 8, crossAxisSpacing: 8, // 让每个子项占满一列宽度,自动适配行内最高高度 staggeredTiles: List.generate(prizes.length, (index) => const StaggeredTile.fit(1)), children: prizes.map((prize) { return Card( elevation: 3.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0)), color: Colors.white, child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Stack( children: [ Image.asset(prize["image"]), ], ), Padding( padding: const EdgeInsets.only(top: 10.0), child: Text( prize["name"], style: const TextStyle(fontWeight: FontWeight.bold), ), ), Padding( padding: const EdgeInsets.only(top: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( prize["cost"].toString(), style: const TextStyle(fontWeight: FontWeight.normal), ), Padding( padding: const EdgeInsets.only(left : 4.0), child: SizedBox( width: 14, height: 14, child: svg), ), ], ), ), Padding( padding: const EdgeInsets.only(top: 10), child: ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.blue), shape: MaterialStateProperty.all<RoundedRectangleBorder>( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ) ) ), onPressed: () async {}, child: Padding( padding: EdgeInsets.all(15.0), child: Text(AppLocalizations.of(context)!.riscuoti, style: TextStyle( fontSize: 16 ), ), ), ), ), ], ), ), ); }).toList(), )
StaggeredTile.fit(1)会自动让同一行的所有子项高度匹配最高的那个,无需手动计算,体验更流畅。
内容的提问来源于stack exchange,提问作者faccio
相关产品推荐
相关产品推荐

