diff --git a/packages/flutter/lib/src/animation/tween.dart b/packages/flutter/lib/src/animation/tween.dart index 1a909bb91d..cdea0af121 100644 --- a/packages/flutter/lib/src/animation/tween.dart +++ b/packages/flutter/lib/src/animation/tween.dart @@ -109,11 +109,15 @@ class RectTween extends Tween { Rect lerp(double t) => Rect.lerp(begin, end, t); } -/// An interpolation between two integers. +/// An interpolation between two integers that rounds. /// /// This class specializes the interpolation of Tween to be -/// appropriate for integers by interpolating between the given begin and end -/// values and then rounding the result to the nearest integer. +/// appropriate for integers by interpolating between the given begin +/// and end values and then rounding the result to the nearest +/// integer. +/// +/// This is the closest approximation to a linear tween that is +/// possible with an integer. Compare to [StepTween]. class IntTween extends Tween { IntTween({ int begin, int end }) : super(begin: begin, end: end); @@ -122,6 +126,23 @@ class IntTween extends Tween { int lerp(double t) => (begin + (end - begin) * t).round(); } +/// An interpolation between two integers that floors. +/// +/// This class specializes the interpolation of Tween to be +/// appropriate for integers by interpolating between the given begin +/// and end values and then using [int.floor()] to return the current +/// integer component, dropping the fractional component. +/// +/// This results in a value that is never greater than the equivalent +/// value from a linear double interpolation. Compare to [IntTween]. +class StepTween extends Tween { + StepTween({ int begin, int end }) : super(begin: begin, end: end); + + // The inherited lerp() function doesn't work with ints because it multiplies + // the begin and end types by a double, and int * double returns a double. + int lerp(double t) => (begin + (end - begin) * t).floor(); +} + /// Transforms the value of the given animation by the given curve. /// /// This class differs from [CurvedAnimation] in that [CurvedAnimation] applies diff --git a/packages/flutter/lib/src/material/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart index 6be84078e2..dbc241107f 100644 --- a/packages/flutter/lib/src/material/progress_indicator.dart +++ b/packages/flutter/lib/src/material/progress_indicator.dart @@ -12,7 +12,7 @@ const double _kLinearProgressIndicatorHeight = 6.0; const double _kMinCircularProgressIndicatorSize = 36.0; const double _kCircularProgressIndicatorStrokeWidth = 4.0; -// TODO(hansmuller) implement the support for buffer indicator +// TODO(hansmuller): implement the support for buffer indicator abstract class ProgressIndicator extends StatefulComponent { ProgressIndicator({ @@ -78,23 +78,6 @@ class LinearProgressIndicator extends ProgressIndicator { }) : super(key: key, value: value); _LinearProgressIndicatorState createState() => new _LinearProgressIndicatorState(); - - Widget _buildIndicator(BuildContext context, double animationValue) { - return new Container( - constraints: new BoxConstraints.tightFor( - width: double.INFINITY, - height: _kLinearProgressIndicatorHeight - ), - child: new CustomPaint( - painter: new _LinearProgressIndicatorPainter( - backgroundColor: _getBackgroundColor(context), - valueColor: _getValueColor(context), - value: value, - animationValue: animationValue - ) - ) - ); - } } class _LinearProgressIndicatorState extends State { @@ -109,14 +92,31 @@ class _LinearProgressIndicatorState extends State { _animation = new CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn); } + Widget _buildIndicator(BuildContext context, double animationValue) { + return new Container( + constraints: new BoxConstraints.tightFor( + width: double.INFINITY, + height: _kLinearProgressIndicatorHeight + ), + child: new CustomPaint( + painter: new _LinearProgressIndicatorPainter( + backgroundColor: config._getBackgroundColor(context), + valueColor: config._getValueColor(context), + value: config.value, // may be null + animationValue: animationValue // ignored if config.value is not null + ) + ) + ); + } + Widget build(BuildContext context) { if (config.value != null) - return config._buildIndicator(context, _animation.value); + return _buildIndicator(context, _animation.value); return new AnimatedBuilder( animation: _animation, builder: (BuildContext context, Widget child) { - return config._buildIndicator(context, _animation.value); + return _buildIndicator(context, _animation.value); } ); } @@ -152,14 +152,14 @@ class _CircularProgressIndicatorPainter extends CustomPainter { ..style = PaintingStyle.stroke; if (value != null) { - // Determinite + // Determinate double angle = value.clamp(0.0, 1.0) * _kSweep; Path path = new Path() ..arcTo(Point.origin & size, _kStartAngle, angle, false); canvas.drawPath(path, paint); } else { - // Non-determinite + // Non-determinate paint.strokeCap = StrokeCap.square; double arcSweep = math.max(headValue * 3 / 2 * math.PI - tailValue * 3 / 2 * math.PI, _kEpsilon); @@ -189,28 +189,9 @@ class CircularProgressIndicator extends ProgressIndicator { }) : super(key: key, value: value); _CircularProgressIndicatorState createState() => new _CircularProgressIndicatorState(); - - Widget _buildIndicator(BuildContext context, double headValue, double tailValue, int stepValue, double rotationValue) { - return new Container( - constraints: new BoxConstraints( - minWidth: _kMinCircularProgressIndicatorSize, - minHeight: _kMinCircularProgressIndicatorSize - ), - child: new CustomPaint( - painter: new _CircularProgressIndicatorPainter( - valueColor: _getValueColor(context), - value: value, - headValue: headValue, - tailValue: tailValue, - stepValue: stepValue, - rotationValue: rotationValue - ) - ) - ); - } } -// TODO(jestelle) This should probably go somewhere else? And maybe be more -// general? + +// This class assumes that the incoming animation is a linear 0.0..1.0. class _RepeatingCurveTween extends Animatable { _RepeatingCurveTween({ this.curve, this.repeats }); @@ -229,31 +210,23 @@ class _RepeatingCurveTween extends Animatable { } } -// TODO(jestelle) This should probably go somewhere else? And maybe be more -// general? Or maybe the IntTween should actually work this way? -class _StepTween extends Tween { - _StepTween({ int begin, int end }) : super(begin: begin, end: end); - - // The inherited lerp() function doesn't work with ints because it multiplies - // the begin and end types by a double, and int * double returns a double. - int lerp(double t) => (begin + (end - begin) * t).floor(); -} - // Tweens used by circular progress indicator -final _RepeatingCurveTween _kStrokeHeadTween = - new _RepeatingCurveTween( - curve:new Interval(0.0, 0.5, curve: Curves.fastOutSlowIn), - repeats:5); +final _RepeatingCurveTween _kStrokeHeadTween = new _RepeatingCurveTween( + curve: new Interval(0.0, 0.5, curve: Curves.fastOutSlowIn), + repeats: 5 +); -final _RepeatingCurveTween _kStrokeTailTween = - new _RepeatingCurveTween( - curve:new Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), - repeats:5); +final _RepeatingCurveTween _kStrokeTailTween = new _RepeatingCurveTween( + curve: new Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), + repeats: 5 +); -final _StepTween _kStepTween = new _StepTween(begin:0, end:5); +final StepTween _kStepTween = new StepTween(begin: 0, end: 5); -final _RepeatingCurveTween _kRotationTween = - new _RepeatingCurveTween(curve:Curves.linear, repeats:5); +final _RepeatingCurveTween _kRotationTween = new _RepeatingCurveTween( + curve: Curves.linear, + repeats: 5 +); class _CircularProgressIndicatorState extends State { AnimationController _animationController; @@ -265,18 +238,39 @@ class _CircularProgressIndicatorState extends State { )..repeat(); } + Widget _buildIndicator(BuildContext context, double headValue, double tailValue, int stepValue, double rotationValue) { + return new Container( + constraints: new BoxConstraints( + minWidth: _kMinCircularProgressIndicatorSize, + minHeight: _kMinCircularProgressIndicatorSize + ), + child: new CustomPaint( + painter: new _CircularProgressIndicatorPainter( + valueColor: config._getValueColor(context), + value: config.value, // may be null + headValue: headValue, // remaining arguments are ignored if config.value is not null + tailValue: tailValue, + stepValue: stepValue, + rotationValue: rotationValue + ) + ) + ); + } + Widget build(BuildContext context) { if (config.value != null) - return config._buildIndicator(context, 0.0, 0.0, 0, 0.0); + return _buildIndicator(context, 0.0, 0.0, 0, 0.0); return new AnimatedBuilder( animation: _animationController, builder: (BuildContext context, Widget child) { - return config._buildIndicator(context, - _kStrokeHeadTween.evaluate(_animationController), - _kStrokeTailTween.evaluate(_animationController), - _kStepTween.evaluate(_animationController), - _kRotationTween.evaluate(_animationController)); + return _buildIndicator( + context, + _kStrokeHeadTween.evaluate(_animationController), + _kStrokeTailTween.evaluate(_animationController), + _kStepTween.evaluate(_animationController), + _kRotationTween.evaluate(_animationController) + ); } ); }