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

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

Issue 1234073005: Simplify the Drawer animation (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Less code 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 | « no previous file | 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
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:sky/animation/animation_performance.dart'; 7 import 'package:sky/animation/animation_performance.dart';
8 import 'package:sky/animation/curves.dart'; 8 import 'package:sky/animation/curves.dart';
9 import 'package:sky/theme/shadows.dart'; 9 import 'package:sky/theme/shadows.dart';
10 import 'package:sky/theme/colors.dart' as colors;
10 import 'package:sky/widgets/animated_component.dart'; 11 import 'package:sky/widgets/animated_component.dart';
11 import 'package:sky/widgets/animation_builder.dart'; 12 import 'package:sky/widgets/animation_builder.dart';
12 import 'package:sky/widgets/basic.dart'; 13 import 'package:sky/widgets/basic.dart';
13 import 'package:sky/widgets/navigator.dart'; 14 import 'package:sky/widgets/navigator.dart';
14 import 'package:sky/widgets/scrollable_viewport.dart'; 15 import 'package:sky/widgets/scrollable_viewport.dart';
15 import 'package:sky/widgets/theme.dart'; 16 import 'package:sky/widgets/theme.dart';
17 import 'package:vector_math/vector_math.dart';
16 18
17 // TODO(eseidel): Draw width should vary based on device size: 19 // TODO(eseidel): Draw width should vary based on device size:
18 // http://www.google.com/design/spec/layout/structure.html#structure-side-nav 20 // http://www.google.com/design/spec/layout/structure.html#structure-side-nav
19 21
20 // Mobile: 22 // Mobile:
21 // Width = Screen width − 56 dp 23 // Width = Screen width − 56 dp
22 // Maximum width: 320dp 24 // Maximum width: 320dp
23 // Maximum width applies only when using a left nav. When using a right nav, 25 // Maximum width applies only when using a left nav. When using a right nav,
24 // the panel can cover the full width of the screen. 26 // the panel can cover the full width of the screen.
25 27
26 // Desktop/Tablet: 28 // Desktop/Tablet:
27 // Maximum width for a left nav is 400dp. 29 // Maximum width for a left nav is 400dp.
28 // The right nav can vary depending on content. 30 // The right nav can vary depending on content.
29 31
30 const double _kWidth = 304.0; 32 const double _kWidth = 304.0;
31 const double _kMinFlingVelocity = 0.4; 33 const double _kMinFlingVelocity = 0.4;
32 const Duration _kBaseSettleDuration = const Duration(milliseconds: 246); 34 const Duration _kBaseSettleDuration = const Duration(milliseconds: 246);
33 // TODO(mpcomplete): The curve must be linear if we want the drawer to track 35 // TODO(mpcomplete): The curve must be linear if we want the drawer to track
34 // the user's finger. Odeon remedies this by attaching spring forces to the 36 // the user's finger. Odeon remedies this by attaching spring forces to the
35 // initial timeline when animating (so it doesn't look linear). 37 // initial timeline when animating (so it doesn't look linear).
38 const Point _kOpenPosition = Point.origin;
39 const Point _kClosedPosition = const Point(-_kWidth, 0.0);
36 const Curve _kAnimationCurve = linear; 40 const Curve _kAnimationCurve = linear;
37 41
38 typedef void DrawerStatusChangeHandler (bool showing); 42 typedef void DrawerStatusChangeHandler (bool showing);
39 43
40 enum DrawerStatus { 44 enum DrawerStatus {
41 active, 45 active,
42 inactive, 46 inactive,
43 } 47 }
44 48
45 typedef void DrawerStatusChangedCallback(DrawerStatus status); 49 typedef void DrawerStatusChangedCallback(DrawerStatus status);
46 50
47 class Drawer extends AnimatedComponent { 51 class Drawer extends AnimatedComponent {
48 Drawer({ 52 Drawer({
49 String key, 53 String key,
50 this.children, 54 this.children,
51 this.showing: false, 55 this.showing: false,
52 this.level: 0, 56 this.level: 0,
53 this.onStatusChanged, 57 this.onStatusChanged,
54 this.navigator 58 this.navigator
55 }) : super(key: key); 59 }) : super(key: key);
56 60
57 List<Widget> children; 61 List<Widget> children;
58 bool showing; 62 bool showing;
59 int level; 63 int level;
60 DrawerStatusChangedCallback onStatusChanged; 64 DrawerStatusChangedCallback onStatusChanged;
61 Navigator navigator; 65 Navigator navigator;
62 66
67 AnimatedType<Point> _position;
68 AnimatedColor _maskColor;
63 AnimationPerformance _performance; 69 AnimationPerformance _performance;
64 AnimationBuilder _builder;
65 70
66 void initState() { 71 void initState() {
67 _builder = new AnimationBuilder() 72 _position = new AnimatedType<Point>(_kClosedPosition, end: _kOpenPosition, c urve: _kAnimationCurve);
68 ..position = new AnimatedType<Point>( 73 _maskColor = new AnimatedColor(colors.transparent, end: const Color(0x7F0000 00));
69 new Point(-_kWidth, 0.0), end: Point.origin, curve: _kAnimationCurve); 74 _performance = new AnimationPerformance()
70 _performance = _builder.createPerformance([_builder.position], 75 ..duration = _kBaseSettleDuration
71 duration: _kBaseSettleDuration) 76 ..variable = new AnimatedList([_position, _maskColor])
72 ..addListener(_checkForStateChanged); 77 ..addListener(_checkForStateChanged);
73 watch(_performance); 78 watch(_performance);
74 if (showing) 79 if (showing)
75 _show(); 80 _show();
76 } 81 }
77 82
83 void syncFields(Drawer source) {
84 children = source.children;
85 level = source.level;
86 navigator = source.navigator;
87 if (showing != source.showing) {
88 showing = source.showing;
89 showing ? _show() : _hide();
90 }
91 onStatusChanged = source.onStatusChanged;
92 super.syncFields(source);
93 }
94
78 void _show() { 95 void _show() {
79 if (navigator != null) 96 if (navigator != null)
80 navigator.pushState(this, (_) => _performance.reverse()); 97 navigator.pushState(this, (_) => _performance.reverse());
81 _performance.play(); 98 _performance.play();
82 } 99 }
83 100
84 void syncFields(Drawer source) { 101 void _hide() {
85 children = source.children; 102 _performance.reverse();
86 level = source.level;
87 navigator = source.navigator;
88 if (showing != source.showing) {
89 showing = source.showing;
90 if (showing) {
91 _show();
92 } else {
93 _performance.reverse();
94 }
95 }
96 onStatusChanged = source.onStatusChanged;
97 super.syncFields(source);
98 } 103 }
99 104
100 // TODO(mpcomplete): the animation system should handle building, maybe? Or
101 // at least setting the transform. Figure out how this could work for things
102 // like fades, slides, rotates, pinch, etc.
103 Widget build() { 105 Widget build() {
104 // TODO(mpcomplete): animate as a fade-in.
105 double scaler = _performance.progress;
106 Color maskColor = new Color.fromARGB((0x7F * scaler).floor(), 0, 0, 0);
107
108 var mask = new Listener( 106 var mask = new Listener(
109 child: new Container(decoration: new BoxDecoration(backgroundColor: maskCo lor)), 107 child: new Container(
108 decoration: new BoxDecoration(backgroundColor: _maskColor.value)
109 ),
110 onGestureTap: handleMaskTap 110 onGestureTap: handleMaskTap
111 ); 111 );
112 112
113 Widget content = _builder.build( 113 Matrix4 transform = new Matrix4.identity();
114 new Container( 114 transform.translate(_position.value.x, _position.value.y);
115 Widget content = new Transform(
116 transform: transform,
117 child: new Container(
115 decoration: new BoxDecoration( 118 decoration: new BoxDecoration(
116 backgroundColor: Theme.of(this).canvasColor, 119 backgroundColor: Theme.of(this).canvasColor,
117 boxShadow: shadows[level]), 120 boxShadow: shadows[level]),
118 width: _kWidth, 121 width: _kWidth,
119 child: new ScrollableBlock(children) 122 child: new ScrollableBlock(children)
120 )); 123 ));
121 124
122 return new Listener( 125 return new Listener(
123 child: new Stack([ mask, content ]), 126 child: new Stack([ mask, content ]),
124 onPointerDown: handlePointerDown, 127 onPointerDown: handlePointerDown,
125 onPointerMove: handlePointerMove, 128 onPointerMove: handlePointerMove,
126 onPointerUp: handlePointerUp, 129 onPointerUp: handlePointerUp,
127 onPointerCancel: handlePointerCancel, 130 onPointerCancel: handlePointerCancel,
128 onGestureFlingStart: handleFlingStart 131 onGestureFlingStart: handleFlingStart
129 ); 132 );
130 } 133 }
131 134
132 double get xPosition => _builder.position.value.x; 135 double get xPosition => _position.value.x;
133 136
134 DrawerStatus _lastStatus; 137 DrawerStatus _lastStatus;
135 void _checkForStateChanged() { 138 void _checkForStateChanged() {
136 DrawerStatus status = _status; 139 DrawerStatus status = _status;
137 if (_lastStatus != null && status != _lastStatus) { 140 if (_lastStatus != null && status != _lastStatus) {
138 if (status == DrawerStatus.inactive && 141 if (status == DrawerStatus.inactive &&
139 navigator != null && 142 navigator != null &&
140 navigator.currentRoute.key == this) 143 navigator.currentRoute.key == this)
141 navigator.pop(); 144 navigator.pop();
142 if (onStatusChanged != null) 145 if (onStatusChanged != null)
143 onStatusChanged(status); 146 onStatusChanged(status);
144 } 147 }
145 _lastStatus = status; 148 _lastStatus = status;
146 } 149 }
147 150
148 DrawerStatus get _status => _performance.isDismissed ? DrawerStatus.inactive : DrawerStatus.active; 151 DrawerStatus get _status => _performance.isDismissed ? DrawerStatus.inactive : DrawerStatus.active;
149 bool get _isMostlyClosed => xPosition <= -_kWidth/2; 152 bool get _isMostlyClosed => xPosition <= -_kWidth/2;
(...skipping 21 matching lines...) Expand all
171 if (!_performance.isAnimating) 174 if (!_performance.isAnimating)
172 _settle(); 175 _settle();
173 } 176 }
174 177
175 void handleFlingStart(event) { 178 void handleFlingStart(event) {
176 double velocityX = event.velocityX / 1000; 179 double velocityX = event.velocityX / 1000;
177 if (velocityX.abs() >= _kMinFlingVelocity) 180 if (velocityX.abs() >= _kMinFlingVelocity)
178 _performance.fling(velocity: velocityX / _kWidth); 181 _performance.fling(velocity: velocityX / _kWidth);
179 } 182 }
180 } 183 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698