Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: sky/sdk/lib/widgets/dismissable.dart

Issue 1237713002: Dismissable component (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Updated per review feedback Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/sdk/example/widgets/card_collection.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 import 'dart:sky' as sky;
6
7 import 'package:vector_math/vector_math.dart';
8 import 'package:sky/animation/animation_performance.dart';
9 import 'package:sky/widgets/animation_builder.dart';
10 import 'package:sky/widgets/animated_component.dart';
11 import 'package:sky/widgets/basic.dart';
12 import 'package:sky/widgets/widget.dart';
13
14 const int _kCardDismissFadeoutMS = 300;
15 const double _kMinFlingVelocity = 700.0;
16 const double _kMinFlingVelocityDelta = 400.0;
17 const double _kDismissCardThreshold = 0.6;
18
19 typedef void DismissedCallback();
20
21 class Dismissable extends AnimatedComponent {
22
23 Dismissable({
24 String key,
25 this.child,
26 this.onDismissed
27 // TODO(hansmuller): direction
28 }) : super(key: key);
29
30 Widget child;
31 DismissedCallback onDismissed;
32
33 AnimationBuilder _transform;
34 AnimationPerformance _performance;
35 double _width;
36 double _dragX = 0.0;
37 bool _dragUnderway = false;
38
39 void initState() {
40 _transform = new AnimationBuilder()
41 ..position = new AnimatedType<Point>(Point.origin)
42 ..opacity = new AnimatedType<double>(1.0, end: 0.0);
43
44 _performance = _transform.createPerformance(
45 [_transform.position, _transform.opacity],
46 duration: new Duration(milliseconds: _kCardDismissFadeoutMS));
47 _performance.addListener(_handleAnimationProgressChanged);
48 watchPerformance(_performance);
49 }
50
51 void syncFields(Dismissable source) {
52 child = source.child;
53 onDismissed = source.onDismissed;
54 super.syncFields(source);
55 }
56
57 Point get _activeCardDragEndPoint {
58 assert(_width != null);
59 return new Point(_dragX.sign * _width * _kDismissCardThreshold, 0.0);
60 }
61
62 bool get _isActive {
63 return _width != null && (_dragUnderway || _performance.isAnimating);
64 }
65
66 void _maybeCallOnDismissed() {
67 if (onDismissed != null)
68 onDismissed();
69 }
70
71 void _handleAnimationProgressChanged() {
72 setState(() {
73 if (_performance.isCompleted && !_dragUnderway)
74 _maybeCallOnDismissed();
75 });
76 }
77
78 void _handleSizeChanged(Size newSize) {
79 _width = newSize.width;
80 _transform.position.end = _activeCardDragEndPoint;
81 }
82
83 void _handlePointerDown(sky.PointerEvent event) {
84 setState(() {
85 _dragUnderway = true;
86 _dragX = 0.0;
87 _performance.progress = 0.0;
88 });
89 }
90
91 void _handlePointerMove(sky.PointerEvent event) {
92 if (!_isActive)
93 return;
94
95 double oldDragX = _dragX;
96 _dragX += event.dx;
97 setState(() {
98 if (!_performance.isAnimating) {
99 if (oldDragX.sign != _dragX.sign)
100 _transform.position.end = _activeCardDragEndPoint;
101 _performance.progress = _dragX.abs() / (_width * _kDismissCardThreshold) ;
102 }
103 });
104 }
105
106 void _handlePointerUpOrCancel(_) {
107 if (!_isActive)
108 return;
109
110 setState(() {
111 _dragUnderway = false;
112 if (_performance.isCompleted)
113 _maybeCallOnDismissed();
114 else if (!_performance.isAnimating)
115 _performance.progress = 0.0;
116 });
117 }
118
119 bool _isHorizontalFlingGesture(sky.GestureEvent event) {
120 double vx = event.velocityX.abs();
121 double vy = event.velocityY.abs();
122 return vx - vy > _kMinFlingVelocityDelta && vx > _kMinFlingVelocity;
123 }
124
125 void _handleFlingStart(sky.GestureEvent event) {
126 if (!_isActive)
127 return;
128
129 if (_isHorizontalFlingGesture(event)) {
130 _dragUnderway = false;
131 double distance = 1.0 - _performance.progress;
132 if (distance > 0.0) {
133 double duration = _kCardDismissFadeoutMS * 1000.0 * distance / event.vel ocityX.abs();
134 _dragX = event.velocityX.sign;
135 _performance.timeline.animateTo(1.0, duration: duration);
136 }
137 }
138 }
139
140 Widget build() {
141 // TODO(hansmuller) The code below changes the widget tree when
142 // the user starts dragging. Currently this causes Sky to drop the
143 // rest of the pointer gesture, see https://github.com/domokit/mojo/issues/3 12.
144 // As a workaround, always create the Transform and Opacity nodes.
145 Widget transformedChild = child;
146 if (_isActive) {
147 transformedChild = _transform.build(transformedChild);
148 } else {
149 transformedChild = new Transform(child: transformedChild, transform: new M atrix4.identity());
150 transformedChild = new Opacity(child: transformedChild, opacity: 1.0);
151 }
152
153 return new Listener(
154 onPointerDown: _handlePointerDown,
155 onPointerMove: _handlePointerMove,
156 onPointerUp: _handlePointerUpOrCancel,
157 onPointerCancel: _handlePointerUpOrCancel,
158 onGestureFlingStart: _handleFlingStart,
159 child: new SizeObserver(
160 child: transformedChild,
161 callback: _handleSizeChanged
162 )
163 );
164 }
165 }
OLDNEW
« no previous file with comments | « sky/sdk/example/widgets/card_collection.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698