Update indeterminate LinearProgressIndicator (#16106)
diff --git a/packages/flutter/lib/src/material/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart
index 3d3050b..cc79780 100644
--- a/packages/flutter/lib/src/material/progress_indicator.dart
+++ b/packages/flutter/lib/src/material/progress_indicator.dart
@@ -12,6 +12,7 @@
const double _kLinearProgressIndicatorHeight = 6.0;
const double _kMinCircularProgressIndicatorSize = 36.0;
+const int _kIndeterminateLinearDuration = 1800;
// TODO(hansmuller): implement the support for buffer indicator
@@ -68,6 +69,29 @@
}
class _LinearProgressIndicatorPainter extends CustomPainter {
+ // The indeterminate progress animation displays two lines whose leading (head)
+ // and trailing (tail) endpoints are defined by the following four curves.
+ static const Curve line1Head = const Interval(
+ 0.0,
+ 750.0 / _kIndeterminateLinearDuration,
+ curve: const Cubic(0.2, 0.0, 0.8, 1.0),
+ );
+ static const Curve line1Tail = const Interval(
+ 333.0 / _kIndeterminateLinearDuration,
+ (333.0 + 750.0) / _kIndeterminateLinearDuration,
+ curve: const Cubic(0.4, 0.0, 1.0, 1.0),
+ );
+ static const Curve line2Head = const Interval(
+ 1000.0 / _kIndeterminateLinearDuration,
+ (1000.0 + 567.0) / _kIndeterminateLinearDuration,
+ curve: const Cubic(0.0, 0.0, 0.65, 1.0),
+ );
+ static const Curve line2Tail = const Interval(
+ 1267.0 / _kIndeterminateLinearDuration,
+ (1267.0 + 533.0) / _kIndeterminateLinearDuration,
+ curve: const Cubic(0.10, 0.0, 0.45, 1.0),
+ );
+
const _LinearProgressIndicatorPainter({
this.backgroundColor,
this.valueColor,
@@ -90,25 +114,10 @@
canvas.drawRect(Offset.zero & size, paint);
paint.color = valueColor;
- if (value != null) {
- final double width = value.clamp(0.0, 1.0) * size.width;
- double left;
- switch (textDirection) {
- case TextDirection.rtl:
- left = size.width - width;
- break;
- case TextDirection.ltr:
- left = 0.0;
- break;
- }
-
- canvas.drawRect(new Offset(left, 0.0) & new Size(width, size.height), paint);
- } else {
- final double startX = size.width * (1.5 * animationValue - 0.5);
- final double endX = startX + 0.5 * size.width;
- final double x = startX.clamp(0.0, size.width);
- final double width = endX.clamp(0.0, size.width) - x;
+ void drawBar(double x, double width) {
+ if (width <= 0.0)
+ return;
double left;
switch (textDirection) {
@@ -119,9 +128,21 @@
left = x;
break;
}
-
canvas.drawRect(new Offset(left, 0.0) & new Size(width, size.height), paint);
}
+
+ if (value != null) {
+ drawBar(0.0, value.clamp(0.0, 1.0) * size.width);
+ } else {
+ final double x1 = size.width * line1Tail.transform(animationValue);
+ final double width1 = size.width * line1Head.transform(animationValue) - x1;
+
+ final double x2 = size.width * line2Tail.transform(animationValue);
+ final double width2 = size.width * line2Head.transform(animationValue) - x2;
+
+ drawBar(x1, width1);
+ drawBar(x2, width2);
+ }
}
@override
@@ -170,18 +191,15 @@
}
class _LinearProgressIndicatorState extends State<LinearProgressIndicator> with SingleTickerProviderStateMixin {
- Animation<double> _animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = new AnimationController(
- duration: const Duration(milliseconds: 1500),
+ duration: const Duration(milliseconds: _kIndeterminateLinearDuration),
vsync: this,
);
- _animation = new CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
-
if (widget.value == null)
_controller.repeat();
}
@@ -224,12 +242,12 @@
final TextDirection textDirection = Directionality.of(context);
if (widget.value != null)
- return _buildIndicator(context, _animation.value, textDirection);
+ return _buildIndicator(context, _controller.value, textDirection);
return new AnimatedBuilder(
- animation: _animation,
+ animation: _controller.view,
builder: (BuildContext context, Widget child) {
- return _buildIndicator(context, _animation.value, textDirection);
+ return _buildIndicator(context, _controller.value, textDirection);
},
);
}
diff --git a/packages/flutter/test/material/progress_indicator_test.dart b/packages/flutter/test/material/progress_indicator_test.dart
index e126ae5..bfdc318 100644
--- a/packages/flutter/test/material/progress_indicator_test.dart
+++ b/packages/flutter/test/material/progress_indicator_test.dart
@@ -100,16 +100,15 @@
),
);
- await tester.pump(const Duration(milliseconds: 750));
-
- final double animationValue = Curves.fastOutSlowIn.transform(0.5);
- final double startX = 200.0 * (1.5 * animationValue - 0.5);
+ await tester.pump(const Duration(milliseconds: 300));
+ final double animationValue = const Interval(0.0, 750.0 / 1800.0, curve: const Cubic(0.2, 0.0, 0.8, 1.0))
+ .transform(300.0 / 1800.0);
expect(
find.byType(LinearProgressIndicator),
paints
..rect(rect: new Rect.fromLTRB(0.0, 0.0, 200.0, 6.0))
- ..rect(rect: new Rect.fromLTRB(startX, 0.0, 200.0, 6.0))
+ ..rect(rect: new Rect.fromLTRB(0.0, 0.0, animationValue * 200.0, 6.0))
);
expect(tester.binding.transientCallbackCount, 1);
@@ -128,16 +127,15 @@
),
);
- await tester.pump(const Duration(milliseconds: 750));
-
- final double animationValue = Curves.fastOutSlowIn.transform(0.5);
- final double startX = 200.0 * (1.5 * animationValue - 0.5);
+ await tester.pump(const Duration(milliseconds: 300));
+ final double animationValue = const Interval(0.0, 750.0 / 1800.0, curve: const Cubic(0.2, 0.0, 0.8, 1.0))
+ .transform(300.0 / 1800.0);
expect(
find.byType(LinearProgressIndicator),
paints
..rect(rect: new Rect.fromLTRB(0.0, 0.0, 200.0, 6.0))
- ..rect(rect: new Rect.fromLTRB(0.0, 0.0, 200.0 - startX, 6.0))
+ ..rect(rect: new Rect.fromLTRB(200.0 - animationValue * 200.0, 0.0, 200.0, 6.0))
);
expect(tester.binding.transientCallbackCount, 1);