提交 d3dbc721 编写于 作者: M Matt Perry

Use transitions for Dismissable.

Simplifies the code a bit.
上级 dd0b5a50
...@@ -137,11 +137,11 @@ class AnimationPerformance { ...@@ -137,11 +137,11 @@ class AnimationPerformance {
} }
Future _animateTo(double target) { Future _animateTo(double target) {
double remainingDistance = (target - timeline.value).abs(); Duration remainingDuration = duration * (target - timeline.value).abs();
timeline.stop(); timeline.stop();
if (remainingDistance == 0.0) if (remainingDuration == Duration.ZERO)
return new Future.value(); return new Future.value();
return timeline.animateTo(target, duration: duration * remainingDistance); return timeline.animateTo(target, duration: remainingDuration);
} }
void _tick(double t) { void _tick(double t) {
......
...@@ -7,14 +7,14 @@ import 'dart:sky' as sky; ...@@ -7,14 +7,14 @@ import 'dart:sky' as sky;
import 'package:sky/animation/animated_value.dart'; import 'package:sky/animation/animated_value.dart';
import 'package:sky/animation/animation_performance.dart'; import 'package:sky/animation/animation_performance.dart';
import 'package:sky/animation/curves.dart'; import 'package:sky/animation/curves.dart';
import 'package:sky/widgets/animated_component.dart';
import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/transitions.dart';
import 'package:sky/widgets/widget.dart'; import 'package:sky/widgets/widget.dart';
import 'package:vector_math/vector_math.dart'; import 'package:vector_math/vector_math.dart';
const Duration _kCardDismissFadeout = const Duration(milliseconds: 200); const Duration _kCardDismissFadeout = const Duration(milliseconds: 200);
const Duration _kCardDismissResize = const Duration(milliseconds: 300); const Duration _kCardDismissResize = const Duration(milliseconds: 300);
const double _kCardDismissResizeDelay = 0.4; final Interval _kCardDismissResizeInterval = new Interval(0.4, 1.0);
const double _kMinFlingVelocity = 700.0; const double _kMinFlingVelocity = 700.0;
const double _kMinFlingVelocityDelta = 400.0; const double _kMinFlingVelocityDelta = 400.0;
const double _kFlingVelocityScale = 1.0 / 300.0; const double _kFlingVelocityScale = 1.0 / 300.0;
...@@ -23,7 +23,7 @@ const double _kDismissCardThreshold = 0.6; ...@@ -23,7 +23,7 @@ const double _kDismissCardThreshold = 0.6;
typedef void ResizedCallback(); typedef void ResizedCallback();
typedef void DismissedCallback(); typedef void DismissedCallback();
class Dismissable extends AnimatedComponent { class Dismissable extends StatefulComponent {
Dismissable({ Dismissable({
Key key, Key key,
...@@ -37,8 +37,6 @@ class Dismissable extends AnimatedComponent { ...@@ -37,8 +37,6 @@ class Dismissable extends AnimatedComponent {
ResizedCallback onResized; ResizedCallback onResized;
DismissedCallback onDismissed; DismissedCallback onDismissed;
AnimatedValue<Point> _position;
AnimatedValue<double> _opacity;
AnimationPerformance _fadePerformance; AnimationPerformance _fadePerformance;
AnimationPerformance _resizePerformance; AnimationPerformance _resizePerformance;
...@@ -47,29 +45,23 @@ class Dismissable extends AnimatedComponent { ...@@ -47,29 +45,23 @@ class Dismissable extends AnimatedComponent {
bool _dragUnderway = false; bool _dragUnderway = false;
void initState() { void initState() {
_position = new AnimatedValue<Point>(Point.origin); _fadePerformance = new AnimationPerformance(duration: _kCardDismissFadeout);
_opacity = new AnimatedValue<double>(1.0, end: 0.0);
_fadePerformance = new AnimationPerformance()
..duration = _kCardDismissFadeout
..variable = new AnimatedList([_position, _opacity])
..addListener(_handleFadeProgressChanged);
} }
void _handleFadeProgressChanged() { void _handleFadeCompleted() {
setState(() { if (!_dragUnderway)
if (_fadePerformance.isCompleted && !_dragUnderway) _startResizePerformance();
_startResizePerformance();
});
} }
void syncFields(Dismissable source) { void syncFields(Dismissable source) {
child = source.child; child = source.child;
onResized = source.onResized; onResized = source.onResized;
onDismissed = source.onDismissed; onDismissed = source.onDismissed;
super.syncFields(source);
} }
Point get _activeCardDragEndPoint { Point get _activeCardDragEndPoint {
if (!_isActive)
return Point.origin;
assert(_size != null); assert(_size != null);
return new Point(_dragX.sign * _size.width * _kDismissCardThreshold, 0.0); return new Point(_dragX.sign * _size.width * _kDismissCardThreshold, 0.0);
} }
...@@ -91,38 +83,27 @@ class Dismissable extends AnimatedComponent { ...@@ -91,38 +83,27 @@ class Dismissable extends AnimatedComponent {
void _startResizePerformance() { void _startResizePerformance() {
assert(_size != null); assert(_size != null);
assert(_fadePerformance != null); assert(_fadePerformance != null);
assert(_fadePerformance.isCompleted);
assert(_resizePerformance == null); assert(_resizePerformance == null);
// TODO(hansmuller): _fadePerformance is completed; stop shouldn't be needed. setState(() {
_fadePerformance.stop(); _resizePerformance = new AnimationPerformance()
..duration = _kCardDismissResize
AnimatedValue<double> dismissHeight = new AnimatedValue<double>(_size.height, ..addListener(_handleResizeProgressChanged);
end: 0.0, });
curve: ease,
interval: new Interval(_kCardDismissResizeDelay, 1.0)
);
_resizePerformance = new AnimationPerformance()
..variable = dismissHeight
..duration = _kCardDismissResize
..addListener(_handleResizeProgressChanged)
..play();
} }
void _handleResizeProgressChanged() { void _handleResizeProgressChanged() {
setState(() { if (_resizePerformance.isCompleted)
if (_resizePerformance.isCompleted) _maybeCallOnDismissed();
_maybeCallOnDismissed(); else
else _maybeCallOnResized();
_maybeCallOnResized();
});
} }
void _handlePointerDown(sky.PointerEvent event) { void _handlePointerDown(sky.PointerEvent event) {
setState(() { _dragUnderway = true;
_dragUnderway = true; _dragX = 0.0;
_dragX = 0.0; _fadePerformance.progress = 0.0;
_fadePerformance.progress = 0.0;
});
} }
void _handlePointerMove(sky.PointerEvent event) { void _handlePointerMove(sky.PointerEvent event) {
...@@ -131,26 +112,21 @@ class Dismissable extends AnimatedComponent { ...@@ -131,26 +112,21 @@ class Dismissable extends AnimatedComponent {
double oldDragX = _dragX; double oldDragX = _dragX;
_dragX += event.dx; _dragX += event.dx;
setState(() { if (oldDragX.sign != _dragX.sign)
if (!_fadePerformance.isAnimating) { setState(() {}); // Rebuild to update the new drag endpoint.
if (oldDragX.sign != _dragX.sign) if (!_fadePerformance.isAnimating)
_position.end = _activeCardDragEndPoint; _fadePerformance.progress = _dragX.abs() / (_size.width * _kDismissCardThreshold);
_fadePerformance.progress = _dragX.abs() / (_size.width * _kDismissCardThreshold);
}
});
} }
void _handlePointerUpOrCancel(_) { void _handlePointerUpOrCancel(_) {
if (!_isActive) if (!_isActive)
return; return;
setState(() { _dragUnderway = false;
_dragUnderway = false; if (_fadePerformance.isCompleted)
if (_fadePerformance.isCompleted) _startResizePerformance();
_startResizePerformance(); else if (!_fadePerformance.isAnimating)
else if (!_fadePerformance.isAnimating) _fadePerformance.reverse();
_fadePerformance.reverse();
});
} }
bool _isHorizontalFlingGesture(sky.GestureEvent event) { bool _isHorizontalFlingGesture(sky.GestureEvent event) {
...@@ -166,24 +142,31 @@ class Dismissable extends AnimatedComponent { ...@@ -166,24 +142,31 @@ class Dismissable extends AnimatedComponent {
if (_isHorizontalFlingGesture(event)) { if (_isHorizontalFlingGesture(event)) {
_dragUnderway = false; _dragUnderway = false;
_dragX = event.velocityX.sign; _dragX = event.velocityX.sign;
_position.end = _activeCardDragEndPoint;
_fadePerformance.fling(Direction.forward, velocity: event.velocityX.abs() * _kFlingVelocityScale); _fadePerformance.fling(Direction.forward, velocity: event.velocityX.abs() * _kFlingVelocityScale);
} }
} }
void _handleSizeChanged(Size newSize) { void _handleSizeChanged(Size newSize) {
_size = new Size.copy(newSize); setState(() {
_position.end = _activeCardDragEndPoint; _size = new Size.copy(newSize);
});
} }
Widget build() { Widget build() {
if (_resizePerformance != null) { if (_resizePerformance != null) {
AnimatedValue<double> height = _resizePerformance.variable; AnimatedValue<double> dismissHeight = new AnimatedValue<double>(
return new Container(height: height.value); _size.height,
end: 0.0,
curve: ease,
interval: _kCardDismissResizeInterval
);
return new SquashTransition(
performance: _resizePerformance,
direction: Direction.forward,
height: dismissHeight);
} }
Matrix4 transform = new Matrix4.identity();
transform.translate(_position.value.x, _position.value.y);
return new Listener( return new Listener(
onPointerDown: _handlePointerDown, onPointerDown: _handlePointerDown,
onPointerMove: _handlePointerMove, onPointerMove: _handlePointerMove,
...@@ -192,10 +175,13 @@ class Dismissable extends AnimatedComponent { ...@@ -192,10 +175,13 @@ class Dismissable extends AnimatedComponent {
onGestureFlingStart: _handleFlingStart, onGestureFlingStart: _handleFlingStart,
child: new SizeObserver( child: new SizeObserver(
callback: _handleSizeChanged, callback: _handleSizeChanged,
child: new Opacity( child: new SlideIn(
opacity: _opacity.value, performance: _fadePerformance,
child: new Transform( position: new AnimatedValue<Point>(Point.origin, end: _activeCardDragEndPoint),
transform: transform, child: new FadeIn(
performance: _fadePerformance,
onCompleted: _handleFadeCompleted,
opacity: new AnimatedValue<double>(1.0, end: 0.0),
child: child child: child
) )
) )
......
...@@ -8,6 +8,8 @@ import 'package:sky/animation/animated_value.dart'; ...@@ -8,6 +8,8 @@ import 'package:sky/animation/animated_value.dart';
import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/basic.dart';
import 'package:vector_math/vector_math.dart'; import 'package:vector_math/vector_math.dart';
dynamic _maybe(AnimatedValue x) => x != null ? x.value : null;
abstract class TransitionBase extends AnimatedComponent { abstract class TransitionBase extends AnimatedComponent {
TransitionBase({ TransitionBase({
Key key, Key key,
...@@ -68,6 +70,7 @@ abstract class TransitionBase extends AnimatedComponent { ...@@ -68,6 +70,7 @@ abstract class TransitionBase extends AnimatedComponent {
Widget build(); Widget build();
} }
// TODO(mpcomplete): rename SlideTransition
class SlideIn extends TransitionBase { class SlideIn extends TransitionBase {
// TODO(mpcomplete): this constructor is mostly boilerplate, passing values // TODO(mpcomplete): this constructor is mostly boilerplate, passing values
// to super. Is there a simpler way? // to super. Is there a simpler way?
...@@ -103,6 +106,7 @@ class SlideIn extends TransitionBase { ...@@ -103,6 +106,7 @@ class SlideIn extends TransitionBase {
} }
} }
// TODO(mpcomplete): rename FadeTransition
class FadeIn extends TransitionBase { class FadeIn extends TransitionBase {
FadeIn({ FadeIn({
Key key, Key key,
...@@ -167,3 +171,40 @@ class ColorTransition extends TransitionBase { ...@@ -167,3 +171,40 @@ class ColorTransition extends TransitionBase {
); );
} }
} }
class SquashTransition extends TransitionBase {
SquashTransition({
Key key,
this.width,
this.height,
Duration duration,
AnimationPerformance performance,
Direction direction,
Function onDismissed,
Function onCompleted,
Widget child
}) : super(key: key,
duration: duration,
performance: performance,
direction: direction,
onDismissed: onDismissed,
onCompleted: onCompleted,
child: child);
AnimatedValue<double> width;
AnimatedValue<double> height;
void syncFields(SquashTransition updated) {
width = updated.width;
height = updated.height;
super.syncFields(updated);
}
Widget build() {
if (width != null)
width.setProgress(performance.progress);
if (height != null)
height.setProgress(performance.progress);
return new SizedBox(width: _maybe(width), height: _maybe(height), child: child);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册