From 79c797a115f2d006b680c35b7d9d4139a6e19eb1 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 6 Jan 2016 16:12:31 -0800 Subject: [PATCH] AnimatedContainer has an issue with one config value change and not another If we're already at the target value, we fail to configure the variable. If another variable animates, we re-animate the other variable. Fixes #958 --- .../lib/src/widgets/animated_container.dart | 54 ++++++++------ .../test/widget/animated_container_test.dart | 70 +++++++++++++++++++ 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/packages/flutter/lib/src/widgets/animated_container.dart b/packages/flutter/lib/src/widgets/animated_container.dart index 31ab3d7c43..54bee6018e 100644 --- a/packages/flutter/lib/src/widgets/animated_container.dart +++ b/packages/flutter/lib/src/widgets/animated_container.dart @@ -146,6 +146,14 @@ class _AnimatedContainerState extends State { _updateCurve(); _performanceController.duration = config.duration; if (_configAllVariables()) { + _updateBeginValue(_constraints); + _updateBeginValue(_decoration); + _updateBeginValue(_foregroundDecoration); + _updateBeginValue(_margin); + _updateBeginValue(_padding); + _updateBeginValue(_transform); + _updateBeginValue(_width); + _updateBeginValue(_height); _performanceController.progress = 0.0; _performanceController.play(); } @@ -183,82 +191,84 @@ class _AnimatedContainerState extends State { }); } - bool _configVariable(AnimatedValue variable, dynamic targetValue) { + bool _updateEndValue(AnimatedValue variable, dynamic targetValue) { if (targetValue == variable.end) return false; - dynamic currentValue = variable.value; variable.end = targetValue; - variable.begin = currentValue; - return currentValue != targetValue; + return true; + } + + void _updateBeginValue(AnimatedValue variable) { + variable?.begin = variable.value; } bool _configAllVariables() { - bool needsAnimation = false; + bool startAnimation = false; if (config.constraints != null) { _constraints ??= new AnimatedBoxConstraintsValue(config.constraints); - if (_configVariable(_constraints, config.constraints)) - needsAnimation = true; + if (_updateEndValue(_constraints, config.constraints)) + startAnimation = true; } else { _constraints = null; } if (config.decoration != null) { _decoration ??= new AnimatedDecorationValue(config.decoration); - if (_configVariable(_decoration, config.decoration)) - needsAnimation = true; + if (_updateEndValue(_decoration, config.decoration)) + startAnimation = true; } else { _decoration = null; } if (config.foregroundDecoration != null) { _foregroundDecoration ??= new AnimatedDecorationValue(config.foregroundDecoration); - if (_configVariable(_foregroundDecoration, config.foregroundDecoration)) - needsAnimation = true; + if (_updateEndValue(_foregroundDecoration, config.foregroundDecoration)) + startAnimation = true; } else { _foregroundDecoration = null; } if (config.margin != null) { _margin ??= new AnimatedEdgeDimsValue(config.margin); - if (_configVariable(_margin, config.margin)) - needsAnimation = true; + if (_updateEndValue(_margin, config.margin)) + startAnimation = true; } else { _margin = null; } if (config.padding != null) { _padding ??= new AnimatedEdgeDimsValue(config.padding); - if (_configVariable(_padding, config.padding)) - needsAnimation = true; + if (_updateEndValue(_padding, config.padding)) + startAnimation = true; } else { _padding = null; } if (config.transform != null) { _transform ??= new AnimatedMatrix4Value(config.transform); - if (_configVariable(_transform, config.transform)) - needsAnimation = true; + if (_updateEndValue(_transform, config.transform)) + startAnimation = true; } else { _transform = null; } if (config.width != null) { _width ??= new AnimatedValue(config.width); - if (_configVariable(_width, config.width)) - needsAnimation = true; + if (_updateEndValue(_width, config.width)) + startAnimation = true; } else { _width = null; } if (config.height != null) { _height ??= new AnimatedValue(config.height); - if (_configVariable(_height, config.height)) - needsAnimation = true; + if (_updateEndValue(_height, config.height)) + startAnimation = true; } else { _height = null; } - return needsAnimation; + return startAnimation; } Widget build(BuildContext context) { diff --git a/packages/flutter/test/widget/animated_container_test.dart b/packages/flutter/test/widget/animated_container_test.dart index e317f11962..fac5763fea 100644 --- a/packages/flutter/test/widget/animated_container_test.dart +++ b/packages/flutter/test/widget/animated_container_test.dart @@ -100,4 +100,74 @@ void main() { expect(tester.binding.transientCallbackCount, 0); }); }); + + test('Animation rerun', () { + testWidgets((WidgetTester tester) { + tester.pumpWidget( + new Center( + child: new AnimatedContainer( + duration: const Duration(milliseconds: 200), + width: 100.0, + height: 100.0, + child: new Text('X') + ) + ) + ); + + tester.pump(); + tester.pump(new Duration(milliseconds: 100)); + + RenderBox text = tester.findText('X').renderObject; + expect(text.size.width, equals(100.0)); + expect(text.size.height, equals(100.0)); + + tester.pump(new Duration(milliseconds: 1000)); + + tester.pumpWidget( + new Center( + child: new AnimatedContainer( + duration: const Duration(milliseconds: 200), + width: 200.0, + height: 200.0, + child: new Text('X') + ) + ) + ); + tester.pump(); + tester.pump(new Duration(milliseconds: 100)); + + text = tester.findText('X').renderObject; + expect(text.size.width, greaterThan(110.0)); + expect(text.size.width, lessThan(190.0)); + expect(text.size.height, greaterThan(110.0)); + expect(text.size.height, lessThan(190.0)); + + tester.pump(new Duration(milliseconds: 1000)); + + expect(text.size.width, equals(200.0)); + expect(text.size.height, equals(200.0)); + + tester.pumpWidget( + new Center( + child: new AnimatedContainer( + duration: const Duration(milliseconds: 200), + width: 200.0, + height: 100.0, + child: new Text('X') + ) + ) + ); + tester.pump(); + tester.pump(new Duration(milliseconds: 100)); + + expect(text.size.width, equals(200.0)); + expect(text.size.height, greaterThan(110.0)); + expect(text.size.height, lessThan(190.0)); + + tester.pump(new Duration(milliseconds: 1000)); + + expect(text.size.width, equals(200.0)); + expect(text.size.height, equals(100.0)); + }); + }); }