Commit 49c47876 authored by Adam Barth's avatar Adam Barth

Convert Drawer to using navigator

This patch converts drawer to using the "openDialog" pattern for managing its
state. Currently, the drawer entrance and exit animation aren't integrated with
the navigator's animation system because the drawer's animations can be stopped
and reversed, which the navigator can't yet understand. That means dismissing
the drawer via the system back button causes the drawer to be removed
instanteously.

Fixes #715
Fixes #1187
parent 49aba0cc
...@@ -66,19 +66,14 @@ class FeedFragmentState extends State<FeedFragment> { ...@@ -66,19 +66,14 @@ class FeedFragmentState extends State<FeedFragment> {
void _handleFitnessModeChange(FitnessMode value) { void _handleFitnessModeChange(FitnessMode value) {
setState(() { setState(() {
_fitnessMode = value; _fitnessMode = value;
_drawerShowing = false;
}); });
config.navigator.pop();
} }
Drawer buildDrawer() { void _showDrawer() {
if (_drawerStatus == AnimationStatus.dismissed) showDrawer(
return null;
return new Drawer(
showing: _drawerShowing,
level: 3,
onDismissed: _handleDrawerDismissed,
navigator: config.navigator, navigator: config.navigator,
children: [ child: new Block([
new DrawerHeader(child: new Text('Fitness')), new DrawerHeader(child: new Text('Fitness')),
new DrawerItem( new DrawerItem(
icon: 'action/view_list', icon: 'action/view_list',
...@@ -98,26 +93,10 @@ class FeedFragmentState extends State<FeedFragment> { ...@@ -98,26 +93,10 @@ class FeedFragmentState extends State<FeedFragment> {
new DrawerItem( new DrawerItem(
icon: 'action/help', icon: 'action/help',
child: new Text('Help & Feedback')) child: new Text('Help & Feedback'))
] ])
); );
} }
bool _drawerShowing = false;
AnimationStatus _drawerStatus = AnimationStatus.dismissed;
void _handleOpenDrawer() {
setState(() {
_drawerShowing = true;
_drawerStatus = AnimationStatus.forward;
});
}
void _handleDrawerDismissed() {
setState(() {
_drawerStatus = AnimationStatus.dismissed;
});
}
void _handleShowSettings() { void _handleShowSettings() {
config.navigator.pop(); config.navigator.pop();
config.navigator.pushNamed('/settings'); config.navigator.pushNamed('/settings');
...@@ -135,7 +114,7 @@ class FeedFragmentState extends State<FeedFragment> { ...@@ -135,7 +114,7 @@ class FeedFragmentState extends State<FeedFragment> {
return new ToolBar( return new ToolBar(
left: new IconButton( left: new IconButton(
icon: "navigation/menu", icon: "navigation/menu",
onPressed: _handleOpenDrawer), onPressed: _showDrawer),
center: new Text(fitnessModeTitle) center: new Text(fitnessModeTitle)
); );
} }
...@@ -262,8 +241,7 @@ class FeedFragmentState extends State<FeedFragment> { ...@@ -262,8 +241,7 @@ class FeedFragmentState extends State<FeedFragment> {
toolbar: buildToolBar(), toolbar: buildToolBar(),
body: buildBody(), body: buildBody(),
snackBar: buildSnackBar(), snackBar: buildSnackBar(),
floatingActionButton: buildFloatingActionButton(), floatingActionButton: buildFloatingActionButton()
drawer: buildDrawer()
); );
} }
} }
......
...@@ -56,22 +56,6 @@ class StockHomeState extends State<StockHome> { ...@@ -56,22 +56,6 @@ class StockHomeState extends State<StockHome> {
}); });
} }
bool _drawerShowing = false;
AnimationStatus _drawerStatus = AnimationStatus.dismissed;
void _handleOpenDrawer() {
setState(() {
_drawerShowing = true;
_drawerStatus = AnimationStatus.forward;
});
}
void _handleDrawerDismissed() {
setState(() {
_drawerStatus = AnimationStatus.dismissed;
});
}
bool _autorefresh = false; bool _autorefresh = false;
void _handleAutorefreshChanged(bool value) { void _handleAutorefreshChanged(bool value) {
setState(() { setState(() {
...@@ -91,16 +75,10 @@ class StockHomeState extends State<StockHome> { ...@@ -91,16 +75,10 @@ class StockHomeState extends State<StockHome> {
); );
} }
Drawer buildDrawer() { void _showDrawer() {
if (_drawerStatus == AnimationStatus.dismissed) showDrawer(
return null;
assert(_drawerShowing); // TODO(mpcomplete): this is always true
return new Drawer(
level: 3,
showing: _drawerShowing,
onDismissed: _handleDrawerDismissed,
navigator: config.navigator, navigator: config.navigator,
children: [ child: new Block([
new DrawerHeader(child: new Text('Stocks')), new DrawerHeader(child: new Text('Stocks')),
new DrawerItem( new DrawerItem(
icon: 'action/assessment', icon: 'action/assessment',
...@@ -141,7 +119,7 @@ class StockHomeState extends State<StockHome> { ...@@ -141,7 +119,7 @@ class StockHomeState extends State<StockHome> {
new DrawerItem( new DrawerItem(
icon: 'action/help', icon: 'action/help',
child: new Text('Help & Feedback')) child: new Text('Help & Feedback'))
] ])
); );
} }
...@@ -154,7 +132,7 @@ class StockHomeState extends State<StockHome> { ...@@ -154,7 +132,7 @@ class StockHomeState extends State<StockHome> {
return new ToolBar( return new ToolBar(
left: new IconButton( left: new IconButton(
icon: "navigation/menu", icon: "navigation/menu",
onPressed: _handleOpenDrawer onPressed: _showDrawer
), ),
center: new Text('Stocks'), center: new Text('Stocks'),
right: [ right: [
...@@ -276,8 +254,7 @@ class StockHomeState extends State<StockHome> { ...@@ -276,8 +254,7 @@ class StockHomeState extends State<StockHome> {
toolbar: _isSearching ? buildSearchBar() : buildToolBar(), toolbar: _isSearching ? buildSearchBar() : buildToolBar(),
body: buildTabNavigator(), body: buildTabNavigator(),
snackBar: buildSnackBar(), snackBar: buildSnackBar(),
floatingActionButton: buildFloatingActionButton(), floatingActionButton: buildFloatingActionButton()
drawer: buildDrawer()
); );
} }
} }
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'dart:sky' as sky; import 'dart:sky' as sky;
import 'package:sky/animation.dart';
import 'package:sky/material.dart'; import 'package:sky/material.dart';
import 'package:sky/painting.dart'; import 'package:sky/painting.dart';
import 'package:sky/widgets.dart'; import 'package:sky/widgets.dart';
...@@ -18,11 +17,15 @@ class CardModel { ...@@ -18,11 +17,15 @@ class CardModel {
Key get key => new ObjectKey(this); Key get key => new ObjectKey(this);
} }
class CardCollectionApp extends StatefulComponent { class CardCollection extends StatefulComponent {
CardCollectionAppState createState() => new CardCollectionAppState(); CardCollection({ this.navigator });
final NavigatorState navigator;
CardCollectionState createState() => new CardCollectionState();
} }
class CardCollectionAppState extends State<CardCollectionApp> { class CardCollectionState extends State<CardCollection> {
static const TextStyle cardLabelStyle = static const TextStyle cardLabelStyle =
const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: bold); const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: bold);
...@@ -37,9 +40,7 @@ class CardCollectionAppState extends State<CardCollectionApp> { ...@@ -37,9 +40,7 @@ class CardCollectionAppState extends State<CardCollectionApp> {
DismissDirection _dismissDirection = DismissDirection.horizontal; DismissDirection _dismissDirection = DismissDirection.horizontal;
bool _snapToCenter = false; bool _snapToCenter = false;
bool _fixedSizeCards = false; bool _fixedSizeCards = false;
bool _drawerShowing = false;
bool _sunshine = false; bool _sunshine = false;
AnimationStatus _drawerStatus = AnimationStatus.dismissed;
InvalidatorCallback _invalidator; InvalidatorCallback _invalidator;
Size _cardCollectionSize = new Size(200.0, 200.0); Size _cardCollectionSize = new Size(200.0, 200.0);
...@@ -114,17 +115,23 @@ class CardCollectionAppState extends State<CardCollectionApp> { ...@@ -114,17 +115,23 @@ class CardCollectionAppState extends State<CardCollectionApp> {
} }
} }
void _handleOpenDrawer() { void _showDrawer() {
setState(() { showDrawer(
_drawerShowing = true; navigator: config.navigator,
_drawerStatus = AnimationStatus.forward; child: new IconTheme(
}); data: const IconThemeData(color: IconThemeColor.black),
} child: new Block([
new DrawerHeader(child: new Text('Options')),
void _handleDrawerDismissed() { buildDrawerCheckbox("Snap fling scrolls to center", _snapToCenter, _toggleSnapToCenter),
setState(() { buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards),
_drawerStatus = AnimationStatus.dismissed; buildDrawerCheckbox("Let the sun shine", _sunshine, _toggleSunshine),
}); new DrawerDivider(),
buildDrawerRadioItem(DismissDirection.horizontal, 'action/code'),
buildDrawerRadioItem(DismissDirection.left, 'navigation/arrow_back'),
buildDrawerRadioItem(DismissDirection.right, 'navigation/arrow_forward'),
])
)
);
} }
String _dismissDirectionText(DismissDirection direction) { String _dismissDirectionText(DismissDirection direction) {
...@@ -151,17 +158,13 @@ class CardCollectionAppState extends State<CardCollectionApp> { ...@@ -151,17 +158,13 @@ class CardCollectionAppState extends State<CardCollectionApp> {
}); });
} }
_changeDismissDirection(DismissDirection newDismissDirection) { void _changeDismissDirection(DismissDirection newDismissDirection) {
setState(() { setState(() {
_dismissDirection = newDismissDirection; _dismissDirection = newDismissDirection;
_drawerStatus = AnimationStatus.dismissed;
}); });
config.navigator.pop();
} }
Widget buildDrawer() {
if (_drawerStatus == AnimationStatus.dismissed)
return null;
Widget buildDrawerCheckbox(String label, bool value, Function callback) { Widget buildDrawerCheckbox(String label, bool value, Function callback) {
return new DrawerItem( return new DrawerItem(
onPressed: callback, onPressed: callback,
...@@ -187,29 +190,9 @@ class CardCollectionAppState extends State<CardCollectionApp> { ...@@ -187,29 +190,9 @@ class CardCollectionAppState extends State<CardCollectionApp> {
); );
} }
return new IconTheme(
data: const IconThemeData(color: IconThemeColor.black),
child: new Drawer(
level: 3,
showing: _drawerShowing,
onDismissed: _handleDrawerDismissed,
children: [
new DrawerHeader(child: new Text('Options')),
buildDrawerCheckbox("Snap fling scrolls to center", _snapToCenter, _toggleSnapToCenter),
buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards),
buildDrawerCheckbox("Let the sun shine", _sunshine, _toggleSunshine),
new DrawerDivider(),
buildDrawerRadioItem(DismissDirection.horizontal, 'action/code'),
buildDrawerRadioItem(DismissDirection.left, 'navigation/arrow_back'),
buildDrawerRadioItem(DismissDirection.right, 'navigation/arrow_forward'),
]
)
);
}
Widget buildToolBar() { Widget buildToolBar() {
return new ToolBar( return new ToolBar(
left: new IconButton(icon: "navigation/menu", onPressed: _handleOpenDrawer), left: new IconButton(icon: "navigation/menu", onPressed: _showDrawer),
center: new Text('Swipe Away'), center: new Text('Swipe Away'),
right: [ right: [
new Text(_dismissDirectionText(_dismissDirection)) new Text(_dismissDirectionText(_dismissDirection))
...@@ -358,24 +341,23 @@ class CardCollectionAppState extends State<CardCollectionApp> { ...@@ -358,24 +341,23 @@ class CardCollectionAppState extends State<CardCollectionApp> {
body = new Stack([body, indicator]); body = new Stack([body, indicator]);
} }
return new Theme( return new Scaffold(
data: new ThemeData(
brightness: ThemeBrightness.light,
primarySwatch: Colors.blue,
accentColor: Colors.redAccent[200]
),
child: new Title(
title: 'Cards',
child: new Scaffold(
toolbar: buildToolBar(), toolbar: buildToolBar(),
drawer: buildDrawer(),
body: body body: body
)
)
); );
} }
} }
void main() { void main() {
runApp(new CardCollectionApp()); runApp(new App(
title: 'Cards',
theme: new ThemeData(
brightness: ThemeBrightness.light,
primarySwatch: Colors.blue,
accentColor: Colors.redAccent[200]
),
routes: {
'/': (NavigatorState navigator, Route route) => new CardCollection(navigator: navigator),
}
));
} }
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:sky/animation.dart';
import 'package:sky/material.dart'; import 'package:sky/material.dart';
import 'package:sky/painting.dart'; import 'package:sky/painting.dart';
import 'package:sky/widgets.dart'; import 'package:sky/widgets.dart';
...@@ -17,6 +16,10 @@ class CardModel { ...@@ -17,6 +16,10 @@ class CardModel {
} }
class PageableListApp extends StatefulComponent { class PageableListApp extends StatefulComponent {
PageableListApp({ this.navigator });
final NavigatorState navigator;
PageableListAppState createState() => new PageableListAppState(); PageableListAppState createState() => new PageableListAppState();
} }
...@@ -85,31 +88,10 @@ class PageableListAppState extends State<PageableListApp> { ...@@ -85,31 +88,10 @@ class PageableListAppState extends State<PageableListApp> {
}); });
} }
bool _drawerShowing = false; void _showDrawer() {
AnimationStatus _drawerStatus = AnimationStatus.dismissed; showDrawer(
navigator: config.navigator,
void _handleOpenDrawer() { child: new Block([
setState(() {
_drawerShowing = true;
_drawerStatus = AnimationStatus.forward;
});
}
void _handleDrawerDismissed() {
setState(() {
_drawerStatus = AnimationStatus.dismissed;
});
}
Drawer buildDrawer() {
if (_drawerStatus == AnimationStatus.dismissed)
return null;
return new Drawer(
level: 3,
showing: _drawerShowing,
onDismissed: _handleDrawerDismissed,
children: [
new DrawerHeader(child: new Text('Options')), new DrawerHeader(child: new Text('Options')),
new DrawerItem( new DrawerItem(
icon: 'navigation/more_horiz', icon: 'navigation/more_horiz',
...@@ -130,14 +112,13 @@ class PageableListAppState extends State<PageableListApp> { ...@@ -130,14 +112,13 @@ class PageableListAppState extends State<PageableListApp> {
new Checkbox(value: itemsWrap) new Checkbox(value: itemsWrap)
]) ])
) )
] ])
); );
} }
Widget buildToolBar() { Widget buildToolBar() {
return new ToolBar( return new ToolBar(
left: new IconButton(icon: "navigation/menu", onPressed: _handleOpenDrawer), left: new IconButton(icon: "navigation/menu", onPressed: _showDrawer),
center: new Text('PageableList'), center: new Text('PageableList'),
right: [ right: [
new Text(scrollDirection == ScrollDirection.horizontal ? "horizontal" : "vertical") new Text(scrollDirection == ScrollDirection.horizontal ? "horizontal" : "vertical")
...@@ -167,25 +148,24 @@ class PageableListAppState extends State<PageableListApp> { ...@@ -167,25 +148,24 @@ class PageableListAppState extends State<PageableListApp> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new IconTheme( return new IconTheme(
data: const IconThemeData(color: IconThemeColor.white), data: const IconThemeData(color: IconThemeColor.white),
child: new Theme(
data: new ThemeData(
brightness: ThemeBrightness.light,
primarySwatch: Colors.blue,
accentColor: Colors.redAccent[200]
),
child: new Title(
title: 'PageableList',
child: new Scaffold( child: new Scaffold(
drawer: buildDrawer(),
toolbar: buildToolBar(), toolbar: buildToolBar(),
body: buildBody(context) body: buildBody(context)
) )
)
)
); );
} }
} }
void main() { void main() {
runApp(new PageableListApp()); runApp(new App(
title: 'PageableList',
theme: new ThemeData(
brightness: ThemeBrightness.light,
primarySwatch: Colors.blue,
accentColor: Colors.redAccent[200]
),
routes: {
'/': (NavigatorState navigator, Route route) => new PageableListApp(navigator: navigator),
}
));
} }
...@@ -79,9 +79,6 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -79,9 +79,6 @@ class AnimationPerformance implements WatchableAnimationPerformance {
/// If non-null, animate with this timing instead of a linear timing /// If non-null, animate with this timing instead of a linear timing
AnimationTiming timing; AnimationTiming timing;
/// If non-null, animate with this force instead of a zero-to-one timeline.
Force attachedForce;
/// The progress of this performance along the timeline /// The progress of this performance along the timeline
/// ///
/// Note: Setting this value stops the current animation. /// Note: Setting this value stops the current animation.
...@@ -136,12 +133,6 @@ class AnimationPerformance implements WatchableAnimationPerformance { ...@@ -136,12 +133,6 @@ class AnimationPerformance implements WatchableAnimationPerformance {
/// Start running this animation in the most recently direction /// Start running this animation in the most recently direction
Future resume() { Future resume() {
if (attachedForce != null) {
return fling(
velocity: _direction == Direction.forward ? 1.0 : -1.0,
force: attachedForce
);
}
return _animateTo(_direction == Direction.forward ? 1.0 : 0.0); return _animateTo(_direction == Direction.forward ? 1.0 : 0.0);
} }
......
...@@ -14,6 +14,7 @@ import 'package:sky/src/widgets/navigator.dart'; ...@@ -14,6 +14,7 @@ import 'package:sky/src/widgets/navigator.dart';
import 'package:sky/src/widgets/scrollable.dart'; import 'package:sky/src/widgets/scrollable.dart';
import 'package:sky/src/widgets/theme.dart'; import 'package:sky/src/widgets/theme.dart';
import 'package:sky/src/widgets/transitions.dart'; import 'package:sky/src/widgets/transitions.dart';
import 'package:sky/src/widgets/focus.dart';
// TODO(eseidel): Draw width should vary based on device size: // TODO(eseidel): Draw width should vary based on device size:
// http://www.google.com/design/spec/layout/structure.html#structure-side-nav // http://www.google.com/design/spec/layout/structure.html#structure-side-nav
...@@ -36,22 +37,16 @@ const Duration _kThemeChangeDuration = const Duration(milliseconds: 200); ...@@ -36,22 +37,16 @@ const Duration _kThemeChangeDuration = const Duration(milliseconds: 200);
const Point _kOpenPosition = Point.origin; const Point _kOpenPosition = Point.origin;
const Point _kClosedPosition = const Point(-_kWidth, 0.0); const Point _kClosedPosition = const Point(-_kWidth, 0.0);
typedef void DrawerDismissedCallback();
class Drawer extends StatefulComponent { class Drawer extends StatefulComponent {
Drawer({ Drawer({
Key key, Key key,
this.children, this.child,
this.showing: false, this.level: 3,
this.level: 0,
this.onDismissed,
this.navigator this.navigator
}) : super(key: key); }) : super(key: key);
final List<Widget> children; final Widget child;
final bool showing;
final int level; final int level;
final DrawerDismissedCallback onDismissed;
final NavigatorState navigator; final NavigatorState navigator;
DrawerState createState() => new DrawerState(); DrawerState createState() => new DrawerState();
...@@ -60,44 +55,24 @@ class Drawer extends StatefulComponent { ...@@ -60,44 +55,24 @@ class Drawer extends StatefulComponent {
class DrawerState extends State<Drawer> { class DrawerState extends State<Drawer> {
void initState() { void initState() {
super.initState(); super.initState();
_performance = new AnimationPerformance(duration: _kBaseSettleDuration); _performance = new AnimationPerformance(duration: _kBaseSettleDuration)
_performance.addStatusListener((AnimationStatus status) { ..addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.dismissed) if (status == AnimationStatus.dismissed)
_handleDismissed(); config.navigator.pop();
});
// Use a spring force for animating the drawer. We can't use curves for
// this because we need a linear curve in order to track the user's finger
// while dragging.
_performance.attachedForce = kDefaultSpringForce;
if (config.navigator != null) {
// TODO(ianh): This is crazy. We should convert drawer to use a pattern like openDialog().
// https://github.com/domokit/sky_engine/pull/1186
scheduleMicrotask(() {
config.navigator.pushState(this, (_) => _performance.reverse());
}); });
} _open();
_performance.play(_direction);
} }
AnimationPerformance _performance; AnimationPerformance _performance;
Direction get _direction => config.showing ? Direction.forward : Direction.reverse;
void didUpdateConfig(Drawer oldConfig) {
if (config.showing != oldConfig.showing)
_performance.play(_direction);
}
Widget build(BuildContext context) { Widget build(BuildContext context) {
var mask = new GestureDetector( Widget mask = new GestureDetector(
onTap: _close,
child: new ColorTransition( child: new ColorTransition(
performance: _performance.view, performance: _performance.view,
color: new AnimatedColorValue(Colors.transparent, end: const Color(0x7F000000)), color: new AnimatedColorValue(Colors.transparent, end: Colors.black54),
child: new Container() child: new Container()
), )
onTap: () {
_performance.reverse();
}
); );
Widget content = new SlideTransition( Widget content = new SlideTransition(
...@@ -105,12 +80,12 @@ class DrawerState extends State<Drawer> { ...@@ -105,12 +80,12 @@ class DrawerState extends State<Drawer> {
position: new AnimatedValue<Point>(_kClosedPosition, end: _kOpenPosition), position: new AnimatedValue<Point>(_kClosedPosition, end: _kOpenPosition),
child: new AnimatedContainer( child: new AnimatedContainer(
curve: ease, curve: ease,
duration: const Duration(milliseconds: 200), duration: _kThemeChangeDuration,
decoration: new BoxDecoration( decoration: new BoxDecoration(
backgroundColor: Theme.of(context).canvasColor, backgroundColor: Theme.of(context).canvasColor,
boxShadow: shadows[config.level]), boxShadow: shadows[config.level]),
width: _kWidth, width: _kWidth,
child: new Block(config.children) child: config.child
) )
); );
...@@ -118,33 +93,64 @@ class DrawerState extends State<Drawer> { ...@@ -118,33 +93,64 @@ class DrawerState extends State<Drawer> {
onHorizontalDragStart: _performance.stop, onHorizontalDragStart: _performance.stop,
onHorizontalDragUpdate: _handleDragUpdate, onHorizontalDragUpdate: _handleDragUpdate,
onHorizontalDragEnd: _handleDragEnd, onHorizontalDragEnd: _handleDragEnd,
child: new Stack([ mask, content ]) child: new Stack([
mask,
new Positioned(
top: 0.0,
left: 0.0,
bottom: 0.0,
child: content
)
])
); );
} }
void _handleDismissed() {
if (config.navigator != null &&
config.navigator.currentRoute is StateRoute &&
(config.navigator.currentRoute as StateRoute).owner == this) // TODO(ianh): remove cast once analyzer is cleverer
config.navigator.pop();
if (config.onDismissed != null)
config.onDismissed();
}
bool get _isMostlyClosed => _performance.progress < 0.5; bool get _isMostlyClosed => _performance.progress < 0.5;
void _settle() { _isMostlyClosed ? _performance.reverse() : _performance.play(); }
void _handleDragUpdate(double delta) { void _handleDragUpdate(double delta) {
_performance.progress += delta / _kWidth; _performance.progress += delta / _kWidth;
} }
void _open() {
_performance.fling(velocity: 1.0);
}
void _close() {
_performance.fling(velocity: -1.0);
}
void _handleDragEnd(Offset velocity) { void _handleDragEnd(Offset velocity) {
if (velocity.dx.abs() >= _kMinFlingVelocity) { if (velocity.dx.abs() >= _kMinFlingVelocity) {
_performance.fling(velocity: velocity.dx * _kFlingVelocityScale); _performance.fling(velocity: velocity.dx * _kFlingVelocityScale);
} else if (_isMostlyClosed) {
_close();
} else { } else {
_settle(); _open();
} }
} }
}
class DrawerRoute extends Route {
DrawerRoute({ this.child, this.level });
final Widget child;
final int level;
bool get opaque => false;
Widget build(NavigatorState navigator, WatchableAnimationPerformance nextRoutePerformance) {
return new Focus(
key: new GlobalObjectKey(this),
autofocus: true,
child: new Drawer(
child: child,
level: level,
navigator: navigator
)
);
}
}
void showDrawer({ NavigatorState navigator, Widget child, int level: 3 }) {
navigator.push(new DrawerRoute(child: child, level: level));
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment