Flutter:带圆形进度指示器的自定义步骤条长文本处理
带步骤进度条的长文本显示问题
我使用Flutter的CustomPaint和Stack组件实现了一个带步骤的进度条,但遇到labelText过长时无法在SizedBox内完整显示的问题。
我的代码
import 'package:flutter/material.dart'; import 'package:percent_indicator/percent_indicator.dart'; class StepperProgressBar extends StatelessWidget { final List<Widget> stepUnits; StepperProgressBar({ super.key, required this.stepUnits, }); @override Widget build(BuildContext context) { return SizedBox( height: 300, width: 450, child: ListView( scrollDirection: Axis.horizontal, children: stepUnits, ), ); } } class StepUnit extends StatelessWidget { final double progressBarHeight; double? progressBarWidth; double? circularStepSize; double? circularStepWidth; final double progressBarValue; final Icon? icon; bool isFirst = false; final Color? backgroundColor; final Color? progressColor; final String? labelText; StepUnit({ super.key, this.progressBarHeight = 5, this.progressBarWidth, this.circularStepSize, this.circularStepWidth, this.progressBarValue = 0.0, this.icon, this.progressColor = const Color.fromARGB(255, 90, 116, 125), this.backgroundColor = const Color.fromARGB(255, 161, 169, 172), this.labelText, }); @override Widget build(BuildContext context) { bool isDone = progressBarValue >= 1; bool isInProgress = progressBarValue > 0 && progressBarValue < 1; final stepUnitBoxWidth = SizedBox(width: 11); progressBarWidth ??= MediaQuery.of(context).size.width * 0.3; circularStepSize ??= MediaQuery.of(context).size.width * 0.11; circularStepWidth ??= MediaQuery.of(context).size.width * 0.1; return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ if (!isFirst) ...[ stepUnitBoxWidth, LinearPercentIndicator( width: progressBarWidth, animation: false, lineHeight: progressBarHeight, animationDuration: 2500, percent: progressBarValue, progressColor: progressColor, backgroundColor: backgroundColor, barRadius: Radius.circular(10), alignment: MainAxisAlignment.start, ), ], stepUnitBoxWidth, SizedBox( height: 300, width: 103, // 扩大宽度以适配长文本 child: Stack( alignment: Alignment.center, children: [ CustomPaint( painter: CirclePainter( isDone: isDone, width: circularStepWidth!, isInProgress: isInProgress, backgroundColor: backgroundColor!, progressColor: progressColor!, ), size: Size(circularStepSize!, circularStepSize!), ), if (isDone) icon ?? const Icon(Icons.done, size: 25, color: Colors.white) else if (icon != null) icon!, if (labelText != null) Positioned( bottom: 30, child: Text( labelText!, style: TextStyle(fontSize: 15, color: Colors.blueGrey), ), ), ], ), ), ], ); } } class CirclePainter extends CustomPainter { final bool isDone; final double width; final bool isInProgress; final Color backgroundColor; final Color progressColor; CirclePainter({ this.isDone = false, this.width = 4, this.isInProgress = false, required this.progressColor, required this.backgroundColor, }); @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = isDone ? progressColor : backgroundColor ..strokeWidth = 4.0 ..style = isInProgress ? PaintingStyle.stroke : PaintingStyle.fill; final center = Offset(size.width / 2, size.height / 2); final radius = size.width / 2; canvas.drawCircle(center, radius, paint); if (isInProgress) { paint.style = PaintingStyle.fill; canvas.drawCircle(center, radius - radius / 3, paint); } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } }
示例使用
List<StepUnit> stepUnits = [ StepUnit( progressBarValue: 1, labelText: 'STEP 1', ), StepUnit( progressBarValue: 1, labelText: 'TEXTTOOLONG', ), StepUnit( progressBarValue: 1, labelText: 'STEP 3', ), StepUnit( progressBarValue: 1, labelText: 'STEP 4', ), ];
问题与尝试
当labelText为长字符串时,无法在SizedBox内完整显示。我尝试扩大Stack外层SizedBox的宽度:
SizedBox( height: 300, width: 103, child: Stack( alignment: Alignment.center, children: [ CustomPaint( painter: CirclePainter( isDone: isDone, width: circularStepWidth!, isInProgress: isInProgress, backgroundColor: backgroundColor!, progressColor: progressColor!, ), size: Size(circularStepSize!, circularStepSize!), ), if (isDone) icon ?? const Icon(Icons.done, size: 25, color: Colors.white) else if (icon != null) icon!, if (labelText != null) Positioned( bottom: 30, child: Text( labelText!, style: TextStyle(fontSize: 15, color: Colors.blueGrey), ), ), ], ), ),
但扩大SizedBox宽度会破坏组件整体布局,无法达到预期效果。
需求
我需要实现Text组件可向右扩展,无论文本长度或字体大小如何,都不会破坏原有布局。
内容的提问来源于stack exchange,提问作者Zaknafein Do'urden
相关产品推荐
相关产品推荐

