Flutter自定义矩形进度条实现详解
在Flutter应用开发中,进度条是一个常见的UI组件,用于展示任务的完成进度。本文将详细介绍如何实现一个支持动画效果的自定义矩形进度条。
功能特点
- 支持圆角矩形外观
- 平滑的动画过渡效果
- 可自定义渐变色
- 可配置边框宽度和颜色
- 支持进度更新动画
实现原理
该进度条的实现主要基于Flutter的CustomPaint
和CustomPainter
,通过绘制路径来实现圆角矩形的进度效果。
1. 基础组件结构
首先,我们创建一个StatefulWidget
来管理进度条的状态:
class RectangleProgressBar extends StatefulWidget {
final double progress;
final Size size;
final double borderRadius;
final Duration duration;
const RectangleProgressBar({
super.key,
required this.progress,
this.size = const Size(200, 200),
this.borderRadius = 20,
this.duration = const Duration(milliseconds: 1000),
});
// ...
}
2. 动画控制
在State
类中,我们使用AnimationController
来控制进度条的动画效果:
class _RectangleProgressBarState extends State<RectangleProgressBar>
with SingleTickerProviderStateMixin {
// ... 初始化代码 ...
@override
void didUpdateWidget(RectangleProgressBar oldWidget) {
if (oldWidget.progress != widget.progress) {
_previousProgress = _animation.value;
_animation = Tween<double>(
begin: _previousProgress,
end: widget.progress,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOutCubic,
));
_controller.reset();
_controller.forward();
}
}
}
3. 自定义绘制器
核心的绘制逻辑在RectangleProgressPainter
类中实现:
class RectangleProgressPainter extends CustomPainter {
// ... 属性定义 ...
@override
void paint(Canvas canvas, Size size) {
final rect = Rect.fromLTWH(0, 0, size.width, size.height);
final path = _createRoundedRectanglePath(size);
_drawBackground(canvas, path);
_drawProgress(canvas, path, rect);
}
}
4. 路径创建
进度条的路径创建是一个重要部分,需要精确控制每个圆角的绘制:
Path _createRoundedRectanglePath(Size size) {
final path = Path();
// 从顶部中点开始绘制
path.moveTo(size.width / 2, 0);
// 绘制右上角
path.lineTo(size.width - borderRadius, 0);
path.arcToPoint(
Offset(size.width, borderRadius),
radius: Radius.circular(borderRadius),
);
// ... 继续绘制其他边和圆角 ...
return path;
}
5. 进度绘制
进度条的绘制使用了路径度量和渐变色:
void _drawProgress(Canvas canvas, Path path, Rect rect) {
final pathMetric = path.computeMetrics().first;
final progressLength = pathMetric.length * value;
final progressPath = Path()
..addPath(
pathMetric.extractPath(0, progressLength),
Offset.zero,
);
final progressPaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round
..strokeJoin = StrokeJoin.miter
..isAntiAlias = true
..shader = LinearGradient(
begin: Alignment.centerRight,
end: Alignment.centerLeft,
colors: valueColors,
).createShader(rect);
canvas.drawPath(progressPath, progressPaint);
}
使用方法
使用这个自定义进度条非常简单:
RectangleProgressBar(
progress: 0.7, // 70%的进度
size: Size(300, 300),
borderRadius: 25,
duration: Duration(milliseconds: 1500),
)
性能优化
为了确保性能,我们实现了shouldRepaint
方法来控制重绘逻辑:
@override
bool shouldRepaint(RectangleProgressPainter oldDelegate) {
return oldDelegate.value != value ||
!listEquals(valueColors, oldDelegate.valueColors) ||
bgStrokeColor != oldDelegate.bgStrokeColor ||
strokeWidth != oldDelegate.strokeWidth ||
progressStrokeWidth != oldDelegate.progressStrokeWidth ||
borderRadius != oldDelegate.borderRadius;
}
总结
这个自定义矩形进度条实现了以下特点:
- 使用
CustomPainter
实现自定义绘制 - 支持平滑的动画效果
- 可自定义外观(颜色、大小、圆角等)
- 使用路径度量实现精确的进度显示
- 支持渐变色效果
通过这个实现,我们不仅创建了一个美观的UI组件,还学习了Flutter中自定义绘制和动画的相关知识。这个组件可以在各种场景下使用,比如文件上传、下载进度显示等。