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,分别放置上、下两行的条目。这种方式能让整体高度自动适配两行中最高的条目高度,同时保留横向滚动能力,完美适配字体大小变化的场景。
修改后代码
- 首先抽离条目构建方法,复用代码:
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, ), ], ) ], ), ), ); }
- 替换原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
相关产品推荐
相关产品推荐

