Flutter中如何用自定义Widget替代Container边框实现随子组件增长的环形进度条
实现方案
你可以通过自定义CustomPainter绘制环形进度条,再封装成通用包裹组件自动适配子组件尺寸,同时绑定进度值和尺寸变化逻辑即可。
第一步:实现环形进度条绘制类
import 'dart:math'; import 'package:flutter/material.dart'; class CircleProgressPainter extends CustomPainter { final double progress; // 取值范围0~1 final double strokeWidth; final Color progressColor; final Color trackColor; CircleProgressPainter({ required this.progress, required this.strokeWidth, required this.progressColor, required this.trackColor, }); @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = (size.shortestSide - strokeWidth) / 2; // 绘制环形轨道 final trackPaint = Paint() ..color = trackColor ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..isAntiAlias = true; canvas.drawCircle(center, radius, trackPaint); // 绘制进度弧 final progressPaint = Paint() ..color = progressColor ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round ..isAntiAlias = true; canvas.drawArc( Rect.fromCircle(center: center, radius: radius), -pi / 2, // 从顶部开始绘制 2 * pi * progress, false, progressPaint, ); } @override bool shouldRepaint(covariant CircleProgressPainter oldDelegate) { return progress != oldDelegate.progress || strokeWidth != oldDelegate.strokeWidth || progressColor != oldDelegate.progressColor || trackColor != oldDelegate.trackColor; } }
第二步:封装自动适配尺寸的进度包裹组件
class CircleProgressWrapper extends StatelessWidget { final Widget child; final double progress; final double strokeWidth; final Color progressColor; final Color trackColor; final Color contentBgColor; final double padding; final List<BoxShadow>? boxShadow; const CircleProgressWrapper({ super.key, required this.child, required this.progress, required this.strokeWidth, required this.progressColor, required this.trackColor, required this.contentBgColor, this.padding = 20, this.boxShadow, }); @override Widget build(BuildContext context) { return IntrinsicHeight( child: IntrinsicWidth( child: Stack( alignment: Alignment.center, children: [ // 内部内容容器 Container( padding: EdgeInsets.all(padding), decoration: BoxDecoration( color: contentBgColor, shape: BoxShape.circle, boxShadow: boxShadow, ), child: child, ), // 外层环形进度条 Positioned.fill( child: CustomPaint( painter: CircleProgressPainter( progress: progress, strokeWidth: strokeWidth, progressColor: progressColor, trackColor: trackColor, ), ), ) ], ), ), ); } }
第三步:替换你的原有代码
直接用封装好的组件替换原有Container即可,只要把控制子组件尺寸变化的变量和progress参数绑定,就能实现进度和尺寸同步增长的效果:
// 示例中progress为0~1的变量,和子组件尺寸变化逻辑同步更新即可 CircleProgressWrapper( progress: progress, strokeWidth: 5, progressColor: Colors.blue, // 替换为你的进度条颜色 trackColor: Colors.transparent, // 如果需要轨道背景色可自行修改 contentBgColor: context.themeCopyExtensions.backgroundColor, padding: 20, boxShadow: [ BoxShadow( color: context.themeCopyExtensions.backgroundColor, blurRadius: 10, ) ], child: ImagesHelper.imagesHelper.getAssetImage(imageName: "logo"), )
内容的提问来源于stack exchange,提问作者Sercan Kaya
相关产品推荐
相关产品推荐

