如何在Flutter DraggableScrollableSheet中实现垂直与水平嵌套ListView
问题解决方案
错误原因梳理
- 你在垂直
ListView的item构建方法中错误使用了Expanded组件:Expanded仅可作为Row/Column这类Flex容器的直接子组件使用,放在滚动列表的item中会触发父组件适配错误,同时导致高度计算无界 - 未将
DraggableScrollableSheet提供的scrollController绑定到外层垂直ListView上,导致滑动逻辑不连通、高度约束无法向下传递 - 水平
ListView属于横向滚动容器,本身不需要和父级垂直滚动抢高度,你不需要用Expanded包裹它,只要给它指定明确高度即可解决高度无界报错
修复后完整bottomsheet.dart代码
class bottomsheet extends StatefulWidget { const bottomsheet({Key? key}) : super(key: key); @override _bottomsheetState createState() => _bottomsheetState(); } class _bottomsheetState extends State<bottomsheet> { @override Widget build(BuildContext context) { List<String> days = time_identifier().generate_days(); return DraggableScrollableSheet( initialChildSize:0.06, minChildSize:0.05, maxChildSize:0.8, builder: (BuildContext context, ScrollController scrollController) { return Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(50), topRight: Radius.circular(50), ) ), // 外层垂直ListView绑定scrollController,连通DraggableScrollableSheet的滑动逻辑 child: ListView.builder( controller: scrollController, itemCount:5, padding: const EdgeInsets.all(20), itemBuilder: (BuildContext context, int index) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children:[ // 可按需添加分组标题类组件 Text("分组$index", style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), const SizedBox(height: 12), // 给水平ListView指定明确高度即可解决高度无界问题,不需要Expanded、shrinkWrap SizedBox( height: 40, child: ListView.builder( scrollDirection:Axis.horizontal, itemCount:5, padding: EdgeInsets.zero, itemBuilder:(BuildContext context, int index){ return Container( margin: const EdgeInsets.only(right: 16), child: Text("Hello World $index"), ); } ), ), const SizedBox(height: 20) ] ); }, ) ); }, ); } }
补充说明
如果你的水平列表高度需要随子组件内容动态适配,可以把包裹水平ListView的SizedBox换成IntrinsicHeight组件即可,固定高度方案性能更优,优先选择固定高度。
内容的提问来源于stack exchange,提问作者Dwikavindra Haryo Radithya
相关产品推荐
相关产品推荐

