Flutter中GridView.builder如何自适应子项高度解决文本溢出
问题根源
溢出错误来自两个不合理的配置:
GridView.builder使用SliverGridDelegateWithFixedCrossAxisCount时写死了mainAxisExtent: 160,强制所有笔记卡片高度为160像素,长文本超出固定高度自然触发溢出。- 卡片组件没有做文本长度兜底处理,且写死了冗余宽度,进一步加剧布局冲突。
可直接复用的解决方案
方案一:使用交错网格(推荐,性能好,还原参考图效果)
如果要实现参考图里错落高度的笔记卡片效果,用专门的自适应网格组件最稳,不需要自己计算文本高度。
- 先在
pubspec.yaml添加依赖:
dependencies: flutter_staggered_grid_view: ^0.7.0
- 替换
HomeScreen里原有GridView.builder的代码,删掉你之前定义的没用到的itemHeight、itemWidth变量:
// 替换原有notes非空判断里的Padding+GridView.builder部分 return Padding( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8), child: StaggeredGrid.count( crossAxisCount: 2, mainAxisSpacing: 8, crossAxisSpacing: 8, children: List.generate(notes.length, (index) { final note = notes[index]; return GestureDetector( onTap: () => Get.to(() => DetailsScreen(id: note.id)), child: BaseContainer(note: note), ); }), ), );
- 修改
BaseContainer组件,移除冗余固定宽度、给Column加自适应配置、给文本加溢出兜底:
import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:samsung_note/Database/database.dart'; import 'package:samsung_note/app_style.dart'; class BaseContainer extends StatelessWidget { final NoteEntityData note ; const BaseContainer({Key? key,required this.note}) : super(key: key); @override Widget build(BuildContext context) { final dateTime = DateFormat.yMMMd().format(note.createdTime); return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30) ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, // 让列高度自适应内容 children: [ const CircleAvatar( backgroundColor: Colors.grey, radius: 4, ), const SizedBox(height: 6), Text( note.title, style: AppStyle.normalTextStyle, maxLines: 2, overflow: TextOverflow.ellipsis, // 标题超长显示省略号 ), const SizedBox(height: 5), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(dateTime,style: AppStyle.smallTextStyle.copyWith(color: Colors.grey),), note.isImportant ? const Icon(Icons.star,color: Colors.orange,size: 20,): const SizedBox.shrink(), ], ), const SizedBox(height: 15), Text( note.description, style: AppStyle.smallTextStyle, maxLines: 10, // 可根据自己需求调整最大显示行数,不需要限制就删掉这行 overflow: TextOverflow.ellipsis, ), ], ), ), ); } }
方案二:不引入第三方依赖
如果不想加额外依赖,可以把网格布局换成Wrap,同样能实现自适应高度,只是笔记量极大时滚动性能略逊于方案一:
- 替换原有
GridView.builder部分代码:
return Padding( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8), child: Wrap( spacing: 8, runSpacing: 8, children: notes.map((note) { return SizedBox( width: (MediaQuery.of(context).size.width - 24) / 2, // 扣除左右边距和列间距,保证两列等宽 child: GestureDetector( onTap: () => Get.to(() => DetailsScreen(id: note.id)), child: BaseContainer(note: note), ), ); }).toList(), ), );
BaseContainer组件的修改和方案一完全一致。
改完后卡片高度会自动适配文本长度,短文本卡片高度更低,长文本自动延展,彻底解决溢出报错。
内容的提问来源于stack exchange,提问作者arash shakibaee
相关产品推荐
相关产品推荐

