diff --git a/packages/flutter/lib/src/widgets/dismissable.dart b/packages/flutter/lib/src/widgets/dismissable.dart index d17eb78013..217b2caca1 100644 --- a/packages/flutter/lib/src/widgets/dismissable.dart +++ b/packages/flutter/lib/src/widgets/dismissable.dart @@ -7,13 +7,13 @@ import 'transitions.dart'; import 'framework.dart'; import 'gesture_detector.dart'; -const Duration _kCardDismissDuration = const Duration(milliseconds: 200); -const Duration _kCardResizeDuration = const Duration(milliseconds: 300); -const Curve _kCardResizeTimeCurve = const Interval(0.4, 1.0, curve: Curves.ease); +const Duration _kDismissDuration = const Duration(milliseconds: 200); +const Duration _kResizeDuration = const Duration(milliseconds: 300); +const Curve _kResizeTimeCurve = const Interval(0.4, 1.0, curve: Curves.ease); const double _kMinFlingVelocity = 700.0; const double _kMinFlingVelocityDelta = 400.0; const double _kFlingVelocityScale = 1.0 / 300.0; -const double _kDismissCardThreshold = 0.4; +const double _kDismissThreshold = 0.4; typedef void DismissDirectionCallback(DismissDirection direction); @@ -93,7 +93,7 @@ class Dismissable extends StatefulComponent { class _DismissableState extends State { void initState() { super.initState(); - _moveController = new AnimationController(duration: _kCardDismissDuration) + _moveController = new AnimationController(duration: _kDismissDuration) ..addStatusListener(_handleDismissStatusChanged); _updateMoveAnimation(); } @@ -231,7 +231,7 @@ class _DismissableState extends State { double flingVelocity = _directionIsXAxis ? velocity.pixelsPerSecond.dx : velocity.pixelsPerSecond.dy; _dragExtent = flingVelocity.sign; _moveController.fling(velocity: flingVelocity.abs() * _kFlingVelocityScale); - } else if (_moveController.value > _kDismissCardThreshold) { + } else if (_moveController.value > _kDismissThreshold) { _moveController.forward(); } else { _moveController.reverse(); @@ -247,16 +247,16 @@ class _DismissableState extends State { assert(_moveController != null); assert(_moveController.isCompleted); assert(_resizeController == null); - _resizeController = new AnimationController(duration: _kCardResizeDuration) + _resizeController = new AnimationController(duration: _kResizeDuration) ..addListener(_handleResizeProgressChanged); _resizeController.forward(); setState(() { _resizeAnimation = new Tween( - begin: _directionIsXAxis ? _findSize().height : _findSize().width, + begin: 1.0, end: 0.0 ).animate(new CurvedAnimation( parent: _resizeController, - curve: _kCardResizeTimeCurve + curve: _kResizeTimeCurve )); }); } @@ -293,15 +293,10 @@ class _DismissableState extends State { return true; }); - return new AnimatedBuilder( - animation: _resizeAnimation, - builder: (BuildContext context, Widget child) { - return new SizedBox( - width: !_directionIsXAxis ? _resizeAnimation.value : null, - height: _directionIsXAxis ? _resizeAnimation.value : null, - child: background - ); - } + return new SizeTransition( + sizeFactor: _resizeAnimation, + axis: _directionIsXAxis ? Axis.horizontal : Axis.vertical, + child: background ); } diff --git a/packages/flutter/lib/src/widgets/transitions.dart b/packages/flutter/lib/src/widgets/transitions.dart index a98b16174c..35f8ca5c73 100644 --- a/packages/flutter/lib/src/widgets/transitions.dart +++ b/packages/flutter/lib/src/widgets/transitions.dart @@ -108,7 +108,7 @@ class SlideTransition extends AnimatedComponent { } } -/// Animates the size of a widget. +/// Animates the scale of transformed widget. class ScaleTransition extends AnimatedComponent { ScaleTransition({ Key key, @@ -171,6 +171,43 @@ class RotationTransition extends AnimatedComponent { } } +/// Animates a widget's width or height. +class SizeTransition extends AnimatedComponent { + SizeTransition({ + Key key, + this.axis: Axis.vertical, + Animation sizeFactor, + this.alignment: const FractionalOffset(0.5, 0.5), + this.child + }) : sizeFactor = sizeFactor, super(key: key, animation: sizeFactor) { + assert(axis != null); + } + + /// [Axis.horizontal] if [sizeFactor] modifies the width, otherwise [Axis.vertical]. + final Axis axis; + + /// The animation that controls the (clipped) size of the child. If the current value + /// of sizeFactor is v then the width or height of the widget will be its intrinsic + /// width or height multiplied by v. + final Animation sizeFactor; + + /// How to align the child. See the [Align] widget. + final FractionalOffset alignment; + + final Widget child; + + Widget build(BuildContext context) { + return new ClipRect( + child: new Align( + alignment: alignment, + heightFactor: axis == Axis.vertical ? sizeFactor.value : null, + widthFactor: axis == Axis.horizontal ? sizeFactor.value : null, + child: child + ) + ); + } +} + /// Animates the opacity of a widget. class FadeTransition extends AnimatedComponent { FadeTransition({