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

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

Issue 1232673003: Delete drawerController and make drawer handle back behavior natively (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Update settings behavior for fitness app as well 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
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 '../animation/animation_performance.dart'; 7 import '../animation/animation_performance.dart';
8 import '../animation/curves.dart'; 8 import '../animation/curves.dart';
9 import '../theme/shadows.dart'; 9 import '../theme/shadows.dart';
10 import 'animated_component.dart'; 10 import 'animated_component.dart';
11 import 'animation_builder.dart'; 11 import 'animation_builder.dart';
12 import 'basic.dart'; 12 import 'basic.dart';
13 import 'scrollable_viewport.dart'; 13 import 'scrollable_viewport.dart';
14 import 'navigator.dart';
14 import 'theme.dart'; 15 import 'theme.dart';
15 16
16 // TODO(eseidel): Draw width should vary based on device size: 17 // TODO(eseidel): Draw width should vary based on device size:
17 // http://www.google.com/design/spec/layout/structure.html#structure-side-nav 18 // http://www.google.com/design/spec/layout/structure.html#structure-side-nav
18 19
19 // Mobile: 20 // Mobile:
20 // Width = Screen width − 56 dp 21 // Width = Screen width − 56 dp
21 // Maximum width: 320dp 22 // Maximum width: 320dp
22 // Maximum width applies only when using a left nav. When using a right nav, 23 // Maximum width applies only when using a left nav. When using a right nav,
23 // the panel can cover the full width of the screen. 24 // the panel can cover the full width of the screen.
24 25
25 // Desktop/Tablet: 26 // Desktop/Tablet:
26 // Maximum width for a left nav is 400dp. 27 // Maximum width for a left nav is 400dp.
27 // The right nav can vary depending on content. 28 // The right nav can vary depending on content.
28 29
29 const double _kWidth = 304.0; 30 const double _kWidth = 304.0;
30 const double _kMinFlingVelocity = 0.4; 31 const double _kMinFlingVelocity = 0.4;
31 const Duration _kBaseSettleDuration = const Duration(milliseconds: 246); 32 const Duration _kBaseSettleDuration = const Duration(milliseconds: 246);
32 // TODO(mpcomplete): The curve must be linear if we want the drawer to track 33 // TODO(mpcomplete): The curve must be linear if we want the drawer to track
33 // the user's finger. Odeon remedies this by attaching spring forces to the 34 // the user's finger. Odeon remedies this by attaching spring forces to the
34 // initial timeline when animating (so it doesn't look linear). 35 // initial timeline when animating (so it doesn't look linear).
35 const Curve _kAnimationCurve = linear; 36 const Curve _kAnimationCurve = linear;
36 37
37 typedef void DrawerStatusChangeHandler (bool showing); 38 typedef void DrawerStatusChangeHandler (bool showing);
38 39
39 class DrawerController { 40 class Drawer extends AnimatedComponent {
40 DrawerController(this.onStatusChange) { 41 Drawer({
41 builder = new AnimationBuilder() 42 String key,
43 this.children,
44 this.showing: false,
45 this.level: 0,
46 this.onStatusChange,
47 this.navigator
48 }) : super(key: key);
49
50 List<Widget> children;
51 bool showing;
52 int level;
53 DrawerStatusChangeHandler onStatusChange;
54 Navigator navigator;
55
56 AnimationPerformance _performance;
57 AnimationBuilder _builder;
58
59 void initState() {
60 _builder = new AnimationBuilder()
42 ..position = new AnimatedType<Point>( 61 ..position = new AnimatedType<Point>(
43 new Point(-_kWidth, 0.0), end: Point.origin, curve: _kAnimationCurve); 62 new Point(-_kWidth, 0.0), end: Point.origin, curve: _kAnimationCurve);
44 performance = builder.createPerformance([builder.position], 63 _performance = _builder.createPerformance([_builder.position],
45 duration: _kBaseSettleDuration) 64 duration: _kBaseSettleDuration)
46 ..addListener(_checkValue); 65 ..addListener(_checkValue);
66 watchPerformance(_performance);
47 } 67 }
48 final DrawerStatusChangeHandler onStatusChange;
49 68
50 AnimationPerformance performance; 69 void syncFields(Drawer source) {
51 AnimationBuilder builder; 70 const String kDrawerRouteName = "[open drawer]";
abarth-chromium 2015/07/11 02:00:54 I wonder if the navigation should let you use opaq
jackson 2015/07/14 18:25:50 I agree, I'll do this in a new CL.
71 children = source.children;
72 level = source.level;
73 navigator = source.navigator;
74 if (showing != source.showing) {
75 showing = source.showing;
76 if (showing) {
77 if (navigator != null) {
78 navigator.pushState(kDrawerRouteName, (_) {
79 onStatusChange(false);
80 });
81 }
82 _performance.play();
83 } else {
84 if (navigator != null && navigator.currentRoute.name == kDrawerRouteName )
85 navigator.pop();
86 _performance.reverse();
87 }
88 }
89 super.syncFields(source);
90 }
52 91
53 double get xPosition => builder.position.value.x; 92 // TODO(mpcomplete): the animation system should handle building, maybe? Or
93 // at least setting the transform. Figure out how this could work for things
94 // like fades, slides, rotates, pinch, etc.
95 Widget build() {
96 if (isClosed) {
97 return new Container(width: 0.0, height: 0.0);
98 }
abarth-chromium 2015/07/11 02:00:54 We should make an |Empty| widget so that this can
jackson 2015/07/14 18:25:49 This isn't needed now that we aren't building when
99
100 // TODO(mpcomplete): animate as a fade-in.
101 double scaler = _performance.progress;
102 Color maskColor = new Color.fromARGB((0x7F * scaler).floor(), 0, 0, 0);
103
104 var mask = new Listener(
105 child: new Container(decoration: new BoxDecoration(backgroundColor: maskCo lor)),
106 onGestureTap: handleMaskTap
107 );
108
109 Widget content = _builder.build(
110 new Container(
111 decoration: new BoxDecoration(
112 backgroundColor: Theme.of(this).canvasColor,
113 boxShadow: shadows[level]),
114 width: _kWidth,
115 child: new ScrollableBlock(children)
116 ));
117
118 return new Listener(
119 child: new Stack([ mask, content ]),
120 onPointerDown: handlePointerDown,
121 onPointerMove: handlePointerMove,
122 onPointerUp: handlePointerUp,
123 onPointerCancel: handlePointerCancel,
124 onGestureFlingStart: handleFlingStart
125 );
126 }
127
128 double get xPosition => _builder.position.value.x;
54 129
55 bool _oldClosedState = true; 130 bool _oldClosedState = true;
56 void _checkValue() { 131 void _checkValue() {
57 var newClosedState = isClosed; 132 bool newClosedState = isClosed;
58 if (onStatusChange != null && _oldClosedState != newClosedState) { 133 if (onStatusChange != null && _oldClosedState != newClosedState) {
59 onStatusChange(!newClosedState); 134 onStatusChange(!newClosedState);
60 _oldClosedState = newClosedState;
61 } 135 }
136 _oldClosedState = newClosedState;
62 } 137 }
63 138
64 bool get isClosed => performance.isDismissed; 139 bool get isClosed => _performance.isDismissed;
65 bool get _isMostlyClosed => xPosition <= -_kWidth/2; 140 bool get _isMostlyClosed => xPosition <= -_kWidth/2;
66 141
67 void open() => performance.play(); 142 void open() => _performance.play();
68 143
69 void close() => performance.reverse(); 144 void close() => _performance.reverse();
abarth-chromium 2015/07/11 02:00:54 We can delete most of these functions. They exist
jackson 2015/07/14 18:25:50 Done.
70 145
71 void _settle() => _isMostlyClosed ? close() : open(); 146 void _settle() => _isMostlyClosed ? close() : open();
72 147
73 void handleMaskTap(_) => close(); 148 void handleMaskTap(_) => close();
abarth-chromium 2015/07/11 02:00:54 e.g., this function can just call _performance.rev
jackson 2015/07/14 18:25:49 Done.
74 149
75 // TODO(mpcomplete): Figure out how to generalize these handlers on a 150 // TODO(mpcomplete): Figure out how to generalize these handlers on a
76 // "PannableThingy" interface. 151 // "PannableThingy" interface.
77 void handlePointerDown(_) => performance.stop(); 152 void handlePointerDown(_) => _performance.stop();
78 153
79 void handlePointerMove(sky.PointerEvent event) { 154 void handlePointerMove(sky.PointerEvent event) {
80 if (performance.isAnimating) 155 if (_performance.isAnimating)
81 return; 156 return;
82 performance.progress += event.dx / _kWidth; 157 _performance.progress += event.dx / _kWidth;
83 } 158 }
84 159
85 void handlePointerUp(_) { 160 void handlePointerUp(_) {
86 if (!performance.isAnimating) 161 if (!_performance.isAnimating)
87 _settle(); 162 _settle();
88 } 163 }
89 164
90 void handlePointerCancel(_) { 165 void handlePointerCancel(_) {
91 if (!performance.isAnimating) 166 if (!_performance.isAnimating)
92 _settle(); 167 _settle();
93 } 168 }
94 169
95 void handleFlingStart(event) { 170 void handleFlingStart(event) {
96 double velocityX = event.velocityX / 1000; 171 double velocityX = event.velocityX / 1000;
97 if (velocityX.abs() >= _kMinFlingVelocity) 172 if (velocityX.abs() >= _kMinFlingVelocity)
98 performance.fling(velocity: velocityX / _kWidth); 173 _performance.fling(velocity: velocityX / _kWidth);
99 } 174 }
100 } 175 }
101
102 class Drawer extends AnimatedComponent {
103 Drawer({
104 String key,
105 this.controller,
106 this.children,
107 this.level: 0
108 }) : super(key: key) {
109 watchPerformance(controller.performance);
110 }
111
112 List<Widget> children;
113 int level;
114 DrawerController controller;
115
116 void syncFields(Drawer source) {
117 children = source.children;
118 level = source.level;
119 controller = source.controller;
120 super.syncFields(source);
121 }
122
123 // TODO(mpcomplete): the animation system should handle building, maybe? Or
124 // at least setting the transform. Figure out how this could work for things
125 // like fades, slides, rotates, pinch, etc.
126 Widget build() {
127 // TODO(mpcomplete): animate as a fade-in.
128 double scaler = controller.performance.progress;
129 Color maskColor = new Color.fromARGB((0x7F * scaler).floor(), 0, 0, 0);
130
131 var mask = new Listener(
132 child: new Container(decoration: new BoxDecoration(backgroundColor: maskCo lor)),
133 onGestureTap: controller.handleMaskTap
134 );
135
136 Widget content = controller.builder.build(
137 new Container(
138 decoration: new BoxDecoration(
139 backgroundColor: Theme.of(this).canvasColor,
140 boxShadow: shadows[level]),
141 width: _kWidth,
142 child: new ScrollableBlock(children)
143 ));
144
145 return new Listener(
146 child: new Stack([ mask, content ]),
147 onPointerDown: controller.handlePointerDown,
148 onPointerMove: controller.handlePointerMove,
149 onPointerUp: controller.handlePointerUp,
150 onPointerCancel: controller.handlePointerCancel,
151 onGestureFlingStart: controller.handleFlingStart
152 );
153 }
154
155 }
OLDNEW
« sky/sdk/example/stocks/lib/stock_home.dart ('K') | « sky/sdk/example/stocks/lib/stock_home.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698