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

Flutter中如何让水平列表高度随内容动态适配?

Flutter 横向自适应高度网格布局解决方案

模型列表

布局效果

List drConsultationModelList = [
  DrConsultationModel(
    "Doctor\nConsultation",
    "Video Call with \nIndia’s best Doctors",
    icon_dr_consultation,
  ),
  DrConsultationModel(
    "Medicines",
    "Get Delivery at \nhome",
    icon_medicine,
  ),
  DrConsultationModel(
    "Lab Tests",
    "Book Lab Test at \nyour Home",
    icon_lab,
  ),
  DrConsultationModel(
    "Homecare",
    "Get treated at Home",
    icon_homecare,
  ),
  DrConsultationModel(
    "Surgeries",
    "Access best Doctors \nFrom the best Hospitals",
    icon_surgeries,
  ),
  DrConsultationModel(
    "Radiology",
    "X-ray/CT SCAN /MRI",
    icon_radiology,
  ),
];

当前Grid布局代码

/*Grid布局*/
Container(
  height: 225.h,
  width: double.infinity,
  padding: EdgeInsets.zero,
  child: GridView.builder(
    scrollDirection: Axis.horizontal,
    primary: false,
    shrinkWrap: true,
    padding: EdgeInsets.only(
        left: 16.w, top: 8.h, right: 16.w),
    gridDelegate:
        const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            childAspectRatio: 0.5,
            mainAxisSpacing: 16.0,
            crossAxisSpacing: 0.0),
    itemCount: drConsultationModelList.length,
    itemBuilder: (context, i) {
      return GestureDetector(
        onTap: () {
          // print("cick tayu"+i.toString());
          if (i == 0) {
            Get.to(
                () => const AllSpecialityListView());
          } else if (i == 1) {
            Get.to(
                () => const Search_Medicine_view());
          } else if (i == 5) {
            Get.to(() =>
                const RadioLogicalAvailableTestListView());
          }
        },
        child: Container(
          width: 210.w,
          margin: EdgeInsets.only(bottom: 15.h),
          padding: EdgeInsets.only(
              left: 16.w,
              bottom: 10.h,
              right: 20.h,
              top: 10.h),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(12.r),
            color: Colors.white,
            boxShadow: const [
              BoxShadow(
                color: Color(0x14000000),
                offset: Offset(
                  0.0,
                  4.0,
                ),
                blurRadius: 14.0,
                spreadRadius: 0.0,
              ), //BoxShadow
            ],
          ),
          child: Row(
            mainAxisAlignment:
                MainAxisAlignment.start,
            mainAxisSize: MainAxisSize.max,
            children: [
              Expanded(
                child: Column(
                  mainAxisAlignment:
                      MainAxisAlignment.center,
                  crossAxisAlignment:
                      CrossAxisAlignment.start,
                  children: [
                    Text(
                      drConsultationModelList[i]
                          .tvTitle,
                    //  textScaleFactor: 1.2,
                      style: TextStyle(
                          fontFamily:
                              fontInterSemibold,
                          fontSize: 15.sp,
                          color: blackes_1a1b25),
                    ),
                    SizedBox(
                      height: 4.h,
                    ),
                    Flexible(
                      child: Text(
                        drConsultationModelList[i]
                            .tvSubTitle,
                        textScaleFactor: 1.0,
                        maxLines: 2,
                        overflow:
                            TextOverflow.ellipsis,
                        style: TextStyle(
                            fontFamily:
                                fontInterRegular,
                            fontSize: 11.sp,
                            color:
                                dark_silver_6a7382),
                      ),
                    )
                  ],
                ),
              ),
              Stack(
                alignment: Alignment.center,
                children: [
                  Container(
                    height: 50.h,
                    width: 50.w,
                    decoration: BoxDecoration(
                      color: const Color(0xffe7f5f0),
                      borderRadius:
                          BorderRadius.circular(8.r),
                    ),
                  ),
                  SvgPicture.asset(
                    drConsultationModelList[i]
                        .imgLogo,
                    width: 34.w,
                    height: 34.h,
                    fit: BoxFit.fill,
                  ),
                ],
              )
            ],
          ),
        ),
      );
    },
  ),
),

问题描述

当前布局必须在外层Container设置固定高度225.h才能显示,但设备默认字体调大时,固定高度会导致布局内容被截断或溢出,无法适配动态内容高度。需要实现无需固定高度、布局高度随内容自动调整的方案。

解决方案

方案思路

放弃GridView实现横向2列布局,改用Column嵌套两个横向滚动的SingleChildScrollView,分别放置上、下两行的条目。这种方式能让整体高度自动适配两行中最高的条目高度,同时保留横向滚动能力,完美适配字体大小变化的场景。

修改后代码

  1. 首先抽离条目构建方法,复用代码:
Widget buildConsultationItem(int index) {
  return GestureDetector(
    onTap: () {
      if (index == 0) {
        Get.to(() => const AllSpecialityListView());
      } else if (index == 1) {
        Get.to(() => const Search_Medicine_view());
      } else if (index == 5) {
        Get.to(() => const RadioLogicalAvailableTestListView());
      }
    },
    child: Container(
      width: 210.w,
      margin: EdgeInsets.only(bottom: 15.h),
      padding: EdgeInsets.only(
          left: 16.w,
          bottom: 10.h,
          right: 20.h,
          top: 10.h),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(12.r),
        color: Colors.white,
        boxShadow: const [
          BoxShadow(
            color: Color(0x14000000),
            offset: Offset(0.0, 4.0),
            blurRadius: 14.0,
            spreadRadius: 0.0,
          ),
        ],
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.max,
        children: [
          Expanded(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  drConsultationModelList[index].tvTitle,
                  style: TextStyle(
                      fontFamily: fontInterSemibold,
                      fontSize: 15.sp,
                      color: blackes_1a1b25),
                ),
                SizedBox(height: 4.h),
                Flexible(
                  child: Text(
                    drConsultationModelList[index].tvSubTitle,
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                    style: TextStyle(
                        fontFamily: fontInterRegular,
                        fontSize: 11.sp,
                        color: dark_silver_6a7382),
                  ),
                )
              ],
            ),
          ),
          Stack(
            alignment: Alignment.center,
            children: [
              Container(
                height: 50.h,
                width: 50.w,
                decoration: BoxDecoration(
                  color: const Color(0xffe7f5f0),
                  borderRadius: BorderRadius.circular(8.r),
                ),
              ),
              SvgPicture.asset(
                drConsultationModelList[index].imgLogo,
                width: 34.w,
                height: 34.h,
                fit: BoxFit.fill,
              ),
            ],
          )
        ],
      ),
    ),
  );
}
  1. 替换原Grid布局为自适应高度布局:
/* 自适应高度的横向2列布局 */
Container(
  width: double.infinity,
  padding: EdgeInsets.only(left: 16.w, top: 8.h, right: 16.w),
  child: Column(
    children: [
      // 第一行条目
      SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: List.generate(3, (index) {
            return Padding(
              padding: EdgeInsets.only(right: 16.w),
              child: buildConsultationItem(index),
            );
          }),
        ),
      ),
      // 两行之间的间距
      SizedBox(height: 16.h),
      // 第二行条目
      SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: List.generate(3, (index) {
            return Padding(
              padding: EdgeInsets.only(right: 16.w),
              child: buildConsultationItem(index + 3),
            );
          }),
        ),
      ),
    ],
  ),
)

方案优势

  • 无需设置任何固定高度,整体高度由内容自动决定,完美适配字体大小调整
  • 保留横向滚动能力,条目过多时可横向滑动查看
  • 代码复用性更高,条目构建逻辑抽离后便于维护和修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 12:00:52