You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何让横向滚动的GridView(FixedCrossAxisCount)适配屏幕宽度?

解决方案

要让横向滚动的GridView适配屏幕宽度,同时避免单元格因高度溢出被隐藏,可以通过以下两种方式修改代码:

方法一:固定宽度并动态调整单元格宽高比

直接强制GridView宽度为屏幕宽度,同时根据屏幕尺寸计算单元格的宽高比,确保垂直方向内容不会超出屏幕范围:

class GridViewCalendar extends StatelessWidget {
  const GridViewCalendar({super.key, required this.monthData});
  final Map<String, dynamic> monthData;

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    final screenHeight = MediaQuery.of(context).size.height;
    // 计算适配屏幕高度的单元格宽高比(减去上下边距各6)
    final aspectRatio = screenWidth / ((screenHeight - 12) / 6);

    return Container(
      margin: const EdgeInsets.all(6),
      width: screenWidth, // 强制宽度匹配屏幕
      child: GridView.builder(
        scrollDirection: Axis.horizontal,
        physics: const AlwaysScrollableScrollPhysics(), // 开启横向滚动
        shrinkWrap: true,
        gridDelegate: GridViewCalendarDelegate(
          monthData: monthData,
          crossAxisCount: 6,
          childAspectRatio: aspectRatio,
        ),
        itemCount: 42,
        itemBuilder: (BuildContext context, index) {
          return Container(
            decoration: BoxDecoration(
              border: Border.all(width: 1, color: Colors.deepPurple),
            ),
            child: Center(child: Text('$index')),
          );
        },
      ),
    );
  }
}

class GridViewCalendarDelegate extends SliverGridDelegateWithFixedCrossAxisCount {
  GridViewCalendarDelegate({
    required this.monthData,
    required super.crossAxisCount,
    super.mainAxisSpacing = 3,
    super.crossAxisSpacing = 3,
    super.childAspectRatio = 1,
  });

  final Map<String, dynamic> monthData;
}

方法二:用SizedBox限制高度

通过SizedBox固定GridView的高度为屏幕可用高度,确保所有单元格在可视范围内显示,同时保持横向滚动特性:

class GridViewCalendar extends StatelessWidget {
  const GridViewCalendar({super.key, required this.monthData});
  final Map<String, dynamic> monthData;

  @override
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;

    return Container(
      margin: const EdgeInsets.all(6),
      child: SizedBox(
        height: screenHeight - 12, // 减去边距,避免内容溢出屏幕
        width: screenWidth,
        child: GridView.builder(
          scrollDirection: Axis.horizontal,
          physics: const AlwaysScrollableScrollPhysics(),
          shrinkWrap: false, // 无需自适应高度,SizedBox已限制尺寸
          gridDelegate: GridViewCalendarDelegate(
            monthData: monthData,
            crossAxisCount: 6,
            childAspectRatio: 1,
          ),
          itemCount: 42,
          itemBuilder: (BuildContext context, index) {
            return Container(
              decoration: BoxDecoration(
                border: Border.all(width: 1, color: Colors.deepPurple),
              ),
              child: Center(child: Text('$index')),
            );
          },
        ),
      ),
    );
  }
}

class GridViewCalendarDelegate extends SliverGridDelegateWithFixedCrossAxisCount {
  GridViewCalendarDelegate({
    required this.monthData,
    required super.crossAxisCount,
    super.mainAxisSpacing = 3,
    super.crossAxisSpacing = 3,
    super.childAspectRatio = 1,
  });

  final Map<String, dynamic> monthData;
}

核心注意点

  • 横向滚动模式下,scrollDirection: Axis.horizontal会将GridView的主轴改为水平方向,此时crossAxisCount代表垂直方向的行数,而非原垂直滚动时的列数。
  • 强制设置width: MediaQuery.of(context).size.width可确保GridView始终适配屏幕宽度。
  • 调整childAspectRatio或用SizedBox限制高度,是解决垂直方向内容溢出、单元格被隐藏的关键。

内容的提问来源于stack exchange,提问作者MavWolverine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:54:50