Flutter问题:如何让垂直虚线自适应右侧列表高度?
解决Flutter垂直虚线动态适配列表高度问题
问题原因
Row的布局逻辑是横向排列,子组件不能直接设置无限高度——Row自身的高度由内部最高子组件决定,直接给CustomPaint指定double.infinity会破坏布局约束,引发报错。
解决方案
方法1:用IntrinsicHeight统一Row内子组件高度
通过IntrinsicHeight包裹Row,强制所有子组件高度匹配右侧列表的实际高度,让虚线自动适配:
var widgetsFinal = <Widget>[ const MenuBar(), Padding( padding: const EdgeInsets.only(left: 50), child: IntrinsicHeight( // 新增:统一Row内所有子组件高度 child: Row( children: [ CustomPaint( painter: VerticalDottedLinePainter( color: const Color.fromRGBO(135, 235, 240, 1), strokeWidth: 2, gapSize: 30, ), size: const Size(2, double.infinity), // 现在会被约束为Row的实际高度 ), const SizedBox(width: 10), Expanded( flex: 2, child: Column( mainAxisAlignment: MainAxisAlignment.start, children: drinkWidgets, ), ), ], ), ), ), ]; return Scaffold( body: Stack( children: <Widget>[ SingleChildScrollView( child: Container(color: Colors.black, child: Column(children: widgetsFinal)), ), ], ), );
方法2:修改VerticalDottedLinePainter适配父组件约束
如果不想用IntrinsicHeight,可以调整Painter逻辑,让它根据父组件的实际约束绘制,无需手动传入高度:
// 修改后的Painter类 class VerticalDottedLinePainter extends CustomPainter { final Color color; final double strokeWidth; final double gapSize; VerticalDottedLinePainter({ required this.color, required this.strokeWidth, required this.gapSize, }); @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = color ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke; double currentY = 0; final dashLength = gapSize; // 可根据需求调整线段长度 while (currentY < size.height) { canvas.drawLine( Offset(size.width / 2, currentY), Offset(size.width / 2, currentY + dashLength), paint, ); currentY += dashLength + gapSize; } } @override bool shouldRepaint(covariant VerticalDottedLinePainter oldDelegate) { return oldDelegate.color != color || oldDelegate.strokeWidth != strokeWidth || oldDelegate.gapSize != gapSize; } }
对应布局修改:
Padding( padding: const EdgeInsets.only(left: 50), child: IntrinsicHeight( child: Row( children: [ SizedBox( width: 2, // 固定虚线宽度 child: CustomPaint( painter: VerticalDottedLinePainter( color: const Color.fromRGBO(135, 235, 240, 1), strokeWidth: 2, gapSize: 30, ), // 不再手动设置size,由父组件约束自动适配高度 ), ), const SizedBox(width: 10), Expanded( flex: 2, child: Column( mainAxisAlignment: MainAxisAlignment.start, children: drinkWidgets, ), ), ], ), ), ),
注意事项
IntrinsicHeight会带来轻微性能开销(需预先计算所有子组件高度),但对于常规长度的列表可忽略;如果是超大型列表,可考虑用LayoutBuilder结合右侧列表的key获取高度,再传递给虚线组件。
内容的提问来源于stack exchange,提问作者Joe Nordling
相关产品推荐
相关产品推荐

