| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:sky' as sky; | 5 import 'dart:sky' as sky; |
| 6 | 6 |
| 7 import 'package:vector_math/vector_math.dart'; | 7 import 'package:vector_math/vector_math.dart'; |
| 8 import 'package:sky/animation/animation_performance.dart'; | 8 import 'package:sky/animation/animation_performance.dart'; |
| 9 import 'package:sky/base/lerp.dart'; | 9 import 'package:sky/base/lerp.dart'; |
| 10 import 'package:sky/painting/text_style.dart'; | 10 import 'package:sky/painting/text_style.dart'; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 new TextStyle(color: White, fontSize: 18.0, fontWeight: bold); | 27 new TextStyle(color: White, fontSize: 18.0, fontWeight: bold); |
| 28 | 28 |
| 29 CardCollectionApp() { | 29 CardCollectionApp() { |
| 30 _activeCardAnimation = new AnimationPerformance() | 30 _activeCardAnimation = new AnimationPerformance() |
| 31 ..variable = new AnimatedType(0.0, 1.0) | 31 ..variable = new AnimatedType(0.0, 1.0) |
| 32 ..duration = new Duration(milliseconds: _kCardDismissFadeoutMS); | 32 ..duration = new Duration(milliseconds: _kCardDismissFadeoutMS); |
| 33 _activeCardAnimation.timeline.onValueChanged.listen(_handleAnimationProgress
Changed); | 33 _activeCardAnimation.timeline.onValueChanged.listen(_handleAnimationProgress
Changed); |
| 34 } | 34 } |
| 35 | 35 |
| 36 int _activeCardIndex = -1; | 36 int _activeCardIndex = -1; |
| 37 double _activeCardAnchorX; | |
| 38 AnimationPerformance _activeCardAnimation; | 37 AnimationPerformance _activeCardAnimation; |
| 39 double _activeCardWidth; | 38 double _activeCardWidth; |
| 39 double _activeCardDragX = 0.0; |
| 40 bool _activeCardDragUnderway = false; | 40 bool _activeCardDragUnderway = false; |
| 41 Set<int> _dismissedCardIndices = new Set<int>(); | 41 Set<int> _dismissedCardIndices = new Set<int>(); |
| 42 | 42 |
| 43 double get _activeCardOpacity => 1.0 - _activeCardAnimation.progress; | 43 double get _activeCardOpacity => 1.0 - _activeCardAnimation.progress; |
| 44 | 44 |
| 45 double get _activeCardOffset { | 45 double get _activeCardOffset { |
| 46 return _activeCardAnimation.progress * _activeCardWidth * _kDismissCardThres
hold; | 46 return _activeCardAnimation.progress * _activeCardDragX.sign * _activeCardWi
dth * _kDismissCardThreshold; |
| 47 } | 47 } |
| 48 | 48 |
| 49 void _handleAnimationProgressChanged(_) { | 49 void _handleAnimationProgressChanged(_) { |
| 50 setState(() { | 50 setState(() { |
| 51 if (_activeCardAnimation.isCompleted && !_activeCardDragUnderway) | 51 if (_activeCardAnimation.isCompleted && !_activeCardDragUnderway) |
| 52 _dismissedCardIndices.add(_activeCardIndex); | 52 _dismissedCardIndices.add(_activeCardIndex); |
| 53 }); | 53 }); |
| 54 } | 54 } |
| 55 | 55 |
| 56 void _handleSizeChanged(Size newSize) { | 56 void _handleSizeChanged(Size newSize) { |
| 57 _activeCardWidth = newSize.width; | 57 _activeCardWidth = newSize.width; |
| 58 } | 58 } |
| 59 | 59 |
| 60 void _handlePointerDown(sky.PointerEvent event, int cardIndex) { | 60 void _handlePointerDown(sky.PointerEvent event, int cardIndex) { |
| 61 setState(() { | 61 setState(() { |
| 62 _activeCardIndex = cardIndex; | 62 _activeCardIndex = cardIndex; |
| 63 _activeCardDragUnderway = true; | 63 _activeCardDragUnderway = true; |
| 64 _activeCardAnchorX = null; | 64 _activeCardDragX = 0.0; |
| 65 _activeCardAnimation.progress = 0.0; | 65 _activeCardAnimation.progress = 0.0; |
| 66 }); | 66 }); |
| 67 } | 67 } |
| 68 | 68 |
| 69 void _handlePointerMove(sky.PointerEvent event) { | 69 void _handlePointerMove(sky.PointerEvent event) { |
| 70 if (_activeCardWidth == null || _activeCardIndex < 0) | 70 if (_activeCardWidth == null || _activeCardIndex < 0) |
| 71 return; | 71 return; |
| 72 | 72 |
| 73 if (_activeCardAnchorX == null) | 73 _activeCardDragX += event.dx; |
| 74 _activeCardAnchorX = event.x - event.dx; | |
| 75 | |
| 76 setState(() { | 74 setState(() { |
| 77 double eventOffsetX = event.x - _activeCardAnchorX; | |
| 78 if (!_activeCardAnimation.isAnimating) | 75 if (!_activeCardAnimation.isAnimating) |
| 79 _activeCardAnimation.progress = eventOffsetX / (_activeCardWidth * _kDis
missCardThreshold); | 76 _activeCardAnimation.progress = _activeCardDragX.abs() / (_activeCardWid
th * _kDismissCardThreshold); |
| 80 }); | 77 }); |
| 81 } | 78 } |
| 82 | 79 |
| 83 void _handlePointerUpOrCancel(_) { | 80 void _handlePointerUpOrCancel(_) { |
| 84 if (_activeCardWidth == null || _activeCardIndex < 0) | 81 if (_activeCardWidth == null || _activeCardIndex < 0) |
| 85 return; | 82 return; |
| 86 | 83 |
| 87 setState(() { | 84 setState(() { |
| 88 _activeCardDragUnderway = false; | 85 _activeCardDragUnderway = false; |
| 89 if (_activeCardAnimation.isCompleted) | 86 if (_activeCardAnimation.isCompleted) |
| 90 _dismissedCardIndices.add(_activeCardIndex); | 87 _dismissedCardIndices.add(_activeCardIndex); |
| 91 else if (!_activeCardAnimation.isAnimating) | 88 else if (!_activeCardAnimation.isAnimating) |
| 92 _activeCardAnimation.progress = 0.0; | 89 _activeCardAnimation.progress = 0.0; |
| 93 }); | 90 }); |
| 94 } | 91 } |
| 95 | 92 |
| 96 void _handleFlingStart(sky.GestureEvent event) { | 93 void _handleFlingStart(sky.GestureEvent event) { |
| 97 if (_activeCardWidth == null || _activeCardIndex < 0) | 94 if (_activeCardWidth == null || _activeCardIndex < 0) |
| 98 return; | 95 return; |
| 99 | 96 |
| 100 _activeCardDragUnderway = false; | 97 _activeCardDragUnderway = false; |
| 101 double velocityX = event.velocityX / 1000; | 98 double velocityX = event.velocityX / 1000; |
| 102 if (velocityX.abs() >= _kMinCardFlingVelocity) | 99 if (velocityX.abs() >= _kMinCardFlingVelocity) { |
| 103 _activeCardAnimation.fling(velocity: velocityX / _activeCardWidth); | 100 double distance = 1.0 - _activeCardAnimation.progress; |
| 101 if (distance > 0.0) { |
| 102 double duration = 150.0 * distance / velocityX.abs(); |
| 103 _activeCardDragX = velocityX.sign; |
| 104 _activeCardAnimation.timeline.animateTo(1.0, duration); |
| 105 } |
| 106 } |
| 104 } | 107 } |
| 105 | 108 |
| 106 Widget _buildCard(int index, Color color) { | 109 Widget _buildCard(int index, Color color) { |
| 107 Widget label = new Center(child: new Text("Item ${index}", style: cardLabelS
tyle)); | 110 Widget label = new Center(child: new Text("Item ${index}", style: cardLabelS
tyle)); |
| 108 Widget card = new Card( | 111 Widget card = new Card( |
| 109 child: new Padding(child: label, padding: const EdgeDims.all(8.0)), | 112 child: new Padding(child: label, padding: const EdgeDims.all(8.0)), |
| 110 color: color | 113 color: color |
| 111 ); | 114 ); |
| 112 | 115 |
| 113 if (index == _activeCardIndex && _activeCardOffset > 0.0) { | 116 // TODO(hansmuller) The code below changes the card's widget tree when |
| 117 // the user starts dragging it. Currently this causes Sky to drop the |
| 118 // rest of the pointer gesture, see https://github.com/domokit/mojo/issues/3
12. |
| 119 // As a workaround, always create the Transform and Opacity nodes. |
| 120 /* |
| 121 if (index == _activeCardIndex) { |
| 114 Matrix4 transform = new Matrix4.identity(); | 122 Matrix4 transform = new Matrix4.identity(); |
| 115 transform.translate(_activeCardOffset, 0.0); | 123 transform.translate(_activeCardOffset, 0.0); |
| 116 card = new Transform(child: card, transform: transform); | 124 card = new Transform(child: card, transform: transform); |
| 117 if (_activeCardAnimation != null) | 125 if (_activeCardAnimation != null) |
| 118 card = new Opacity(child: card, opacity: _activeCardOpacity); | 126 card = new Opacity(child: card, opacity: _activeCardOpacity); |
| 119 } | 127 } |
| 128 */ |
| 129 Matrix4 transform = new Matrix4.identity(); |
| 130 double opacity = 1.0; |
| 131 if (index == _activeCardIndex) { |
| 132 transform.translate(_activeCardOffset, 0.0); |
| 133 opacity = _activeCardOpacity; |
| 134 } |
| 135 card = new Transform( |
| 136 child: new Opacity(child: card, opacity: opacity), |
| 137 transform: transform); |
| 120 | 138 |
| 121 return new Listener( | 139 return new Listener( |
| 122 child: card, | 140 child: card, |
| 123 onPointerDown: (event) { _handlePointerDown(event, index); } | 141 onPointerDown: (event) { _handlePointerDown(event, index); }, |
| 142 onPointerMove: _handlePointerMove, |
| 143 onPointerUp: _handlePointerUpOrCancel, |
| 144 onPointerCancel: _handlePointerUpOrCancel, |
| 145 onGestureFlingStart: _handleFlingStart |
| 124 ); | 146 ); |
| 125 } | 147 } |
| 126 | 148 |
| 127 Widget _buildCardCollection(List<double> heights) { | 149 Widget _buildCardCollection(List<double> heights) { |
| 128 List<Widget> items = <Widget>[]; | 150 List<Widget> items = <Widget>[]; |
| 129 for(int index = 0; index < heights.length; index++) { | 151 for(int index = 0; index < heights.length; index++) { |
| 130 if (_dismissedCardIndices.contains(index)) | 152 if (_dismissedCardIndices.contains(index)) |
| 131 continue; | 153 continue; |
| 132 Color color = lerpColor(Red[500], Blue[500], index / heights.length); | 154 Color color = lerpColor(Red[500], Blue[500], index / heights.length); |
| 133 items.add(new Container( | 155 items.add(new Container( |
| 134 child: _buildCard(index, color), | 156 child: _buildCard(index, color), |
| 135 height: heights[index] | 157 height: heights[index] |
| 136 )); | 158 )); |
| 137 } | 159 } |
| 138 | 160 |
| 139 Widget collection = new Container( | 161 return new Container( |
| 140 child: new SizeObserver(child: new Block(items), callback: _handleSizeChan
ged), | 162 child: new SizeObserver(child: new Block(items), callback: _handleSizeChan
ged), |
| 141 padding: const EdgeDims.symmetric(vertical: 12.0, horizontal: 8.0), | 163 padding: const EdgeDims.symmetric(vertical: 12.0, horizontal: 8.0), |
| 142 decoration: new BoxDecoration(backgroundColor: Theme.of(this).primarySwatc
h[50]) | 164 decoration: new BoxDecoration(backgroundColor: Theme.of(this).primarySwatc
h[50]) |
| 143 ); | 165 ); |
| 144 | |
| 145 return new Listener( | |
| 146 child: collection, | |
| 147 onPointerMove: _handlePointerMove, | |
| 148 onPointerUp: _handlePointerUpOrCancel, | |
| 149 onPointerCancel: _handlePointerUpOrCancel, | |
| 150 onGestureFlingStart: _handleFlingStart | |
| 151 ); | |
| 152 } | 166 } |
| 153 | 167 |
| 154 Widget build() { | 168 Widget build() { |
| 155 return new Scaffold( | 169 return new Scaffold( |
| 156 toolbar: new ToolBar(center: new Text('Swipe Away')), | 170 toolbar: new ToolBar(center: new Text('Swipe Away')), |
| 157 body: _buildCardCollection( | 171 body: _buildCardCollection( |
| 158 [48.0, 64.0, 82.0, 46.0, 60.0, 55.0, 84.0, 96.0, 50.0, | 172 [48.0, 64.0, 82.0, 46.0, 60.0, 55.0, 84.0, 96.0, 50.0, |
| 159 48.0, 64.0, 82.0, 46.0, 60.0, 55.0, 84.0, 96.0, 50.0]) | 173 48.0, 64.0, 82.0, 46.0, 60.0, 55.0, 84.0, 96.0, 50.0]) |
| 160 ); | 174 ); |
| 161 } | 175 } |
| 162 } | 176 } |
| 163 | 177 |
| 164 void main() { | 178 void main() { |
| 165 runApp(new CardCollectionApp()); | 179 runApp(new CardCollectionApp()); |
| 166 } | 180 } |
| OLD | NEW |