You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mohemm-flutter-app/lib/widgets/AnimatedProgressBar.dart

177 lines
4.8 KiB
Dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
/// Animated progress bar. Behaves like implicitly animated widget.
/// Check basic implicit animated Flutter widgets like [AnimatedContainer]
/// It animates [value] changes.
/// Requires [duration] to set filling duration timer
/// [onEnd] callback to trigger additional actions (e.g. another animation)
/// at the end of the current animation
/// [color] or [gradient] to fill the progress bar. Only one parameter is allowed.
/// Optional [backgroundColor], defaults to transparent
/// Optional [width] defaults to 200.0
/// Optional [height] defaults to 10.0
/// Optional [curve] defaults to [Curves.linear]
class AnimatedProgressBar extends ImplicitlyAnimatedWidget {
const AnimatedProgressBar({
key,
required duration,
required this.value,
this.width = 200.0,
this.height = 10.0,
this.color,
this.gradient,
this.backgroundColor = Colors.transparent,
curve = Curves.linear,
onEnd,
}) : super(key: key, duration: duration, curve: curve, onEnd: onEnd);
///progress bar width
final double width;
///progress bar height
final double height;
///current progress value
final double? value;
///progress bar gradient parameter
final Gradient? gradient;
///progress bar color parameter
final Color? color;
///progress bar color parameter
final Color backgroundColor;
@override
AnimatedWidgetBaseState<AnimatedProgressBar> createState() => _AnimatedBarState();
}
class _AnimatedBarState extends AnimatedWidgetBaseState<AnimatedProgressBar> {
Tween<double>? _progressValue;
@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_progressValue = visitor(_progressValue, widget.value, (value) => Tween<double>(begin: value)) as Tween<double>?;
}
@override
Widget build(BuildContext context) {
return ProgressBar(
value: _progressValue?.evaluate(animation),
width: widget.width,
height: widget.height,
gradient: widget.gradient,
color: widget.color,
backgroundColor: widget.backgroundColor,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description);
description.add(DiagnosticsProperty<Tween>('progressValue', _progressValue, showName: false, defaultValue: null));
}
}
class ProgressBar extends StatelessWidget {
const ProgressBar({
Key? key,
required this.value,
this.width = 200.0,
this.height = 10.0,
this.color,
this.backgroundColor = Colors.transparent,
this.gradient,
}) : assert(
gradient == null || color == null,
'Cannot provide both a color and a gradient',
),
assert(
gradient != null || color != null,
'Need to provide color or gradient',
),
super(key: key);
///progress bar width
final double width;
///progress bar height
final double height;
///current progress value
final double? value;
///progress bar gradient parameter
final Gradient? gradient;
///progress bar color parameter
final Color? color;
///progress bar color parameter
final Color backgroundColor;
@override
Widget build(BuildContext context) {
return CustomPaint(
size: Size(width, height),
foregroundPainter: ProgressPainter(
value: value!,
color: color,
gradient: gradient,
),
painter: BackgroundPainter(
backgroundColor: backgroundColor,
),
);
}
}
class BackgroundPainter extends CustomPainter {
const BackgroundPainter({required this.backgroundColor});
///progress bar backgroundColor
final Color backgroundColor;
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()..color = backgroundColor;
canvas.drawRRect(RRect.fromRectAndRadius(Offset.zero & size, Radius.circular(6)), paint);
}
@override
bool shouldRepaint(covariant BackgroundPainter oldDelegate) => false;
}
class ProgressPainter extends CustomPainter {
const ProgressPainter({required this.value, this.gradient, this.color});
///current progress bar value
final double value;
///progress bar gradient infill
final Gradient? gradient;
///progress bar gradient color
final Color? color;
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
if (gradient != null) {
paint.shader = gradient?.createShader(Offset.zero & size);
}
if (color != null) {
paint.color = color!;
}
canvas.clipRRect(RRect.fromRectAndRadius(Offset.zero & size, Radius.circular(6)));
canvas.drawRRect(RRect.fromRectAndRadius(Rect.fromLTRB(0, 0, size.width * value, size.height), Radius.circular(6)), paint);
}
@override
bool shouldRepaint(covariant ProgressPainter oldDelegate) {
return value != oldDelegate.value;
}
}