Flutter使用Wrap Widget实现日历日期布局时无法自动扩展导致溢出问题
问题排查及解决方案
问题根源
你遇到的问题由两个错误布局逻辑叠加导致:
- Wrap外层嵌套了Row组件,Row的水平方向是无界约束,Wrap无法获取到最大可用宽度,会一直沿水平方向排列子元素,最终导致溢出。
- 你删除Row后,DaysContainer没有设置固定宽高,默认会占满父容器的整行宽度,导致每行只能容纳1个日期组件,看起来就变成了垂直排列。
修复步骤
- 删掉Wrap外层多余的Row组件,直接让Wrap作为外层固定宽高Container的子节点,获取明确的宽高约束
- 给DaysContainer添加固定宽高,宽度根据父容器宽度、一行要展示的日期数、水平间距计算得出
- 给Wrap添加
runSpacing属性设置行与行之间的垂直间距,优化展示效果
核心修改代码
日历主体部分修改
Container( height: MediaQuery.of(context).size.height * 0.25, width: MediaQuery.of(context).size.width / 2.5, child: Wrap( alignment: WrapAlignment.start, direction: Axis.horizontal, spacing: 2.0, runSpacing: 2.0, // 新增垂直行间距 children: dayList == null ? [] : dayList.map((e) { // 计算单个日期项的宽度:(父容器总宽度 - 总水平间距) / 每行7个日期 final itemWidth = (MediaQuery.of(context).size.width / 2.5 - 2 * 6) / 7; return DaysContainer( number: e, itemWidth: itemWidth, ); }).toList(), ), )
DaysContainer类修改
class DaysContainer extends StatelessWidget { const DaysContainer({Key? key, this.number, this.isAvailable, required this.itemWidth}) : super(key: key); final String? number; final bool? isAvailable; final double itemWidth; @override Widget build(BuildContext context) { return Container( width: itemWidth, height: itemWidth, // 宽高一致做成正方形日期格 padding: EdgeInsets.all(8.0), decoration: BoxDecoration( color: Color(0xFFFFFFFF), ), child: Center( child: Text( number ?? "", style: GoogleFonts.baloo( fontSize: 30.0, color: Color(0xFFBFBFBF), fontWeight: FontWeight.w400, ), ), ), ); } }
原理说明
Wrap组件只有拿到父级传递的最大宽度约束时,才会自动计算一行可容纳的子元素数量,超出后自动换行。之前嵌套Row时Row水平无界,Wrap无法判断换行阈值,所以一直水平排列溢出。删除Row后父容器传递了明确的宽度约束,但子项没有固定宽度默认占满整行,所以每行只能放1个,调整子项宽度后即可实现预期的多行网格布局。
内容的提问来源于stack exchange,提问作者Zahid Tekbaş
相关产品推荐
相关产品推荐

