Commit 68acd261 authored by Adam Barth's avatar Adam Barth

The Drawer should animate out when popped off the navigator

Now with more clear ownership over the Performance.
parent d45bf145
...@@ -34,63 +34,45 @@ const Duration _kThemeChangeDuration = const Duration(milliseconds: 200); ...@@ -34,63 +34,45 @@ 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);
class Drawer extends StatefulComponent { class _Drawer extends StatelessComponent {
Drawer({ _Drawer({
Key key, Key key,
this.child, this.child,
this.level: 3, this.level: 3,
this.navigator this.performance,
this.route
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget child;
final int level; final int level;
final NavigatorState navigator; final PerformanceView performance;
final _DrawerRoute route;
DrawerState createState() => new DrawerState();
}
class DrawerState extends State<Drawer> {
void initState() {
super.initState();
_performance = new Performance(duration: _kBaseSettleDuration)
..addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.dismissed)
config.navigator.pop();
});
_open();
}
Performance _performance;
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget mask = new GestureDetector( Widget mask = new GestureDetector(
onTap: _close, onTap: route.close,
child: new ColorTransition( child: new ColorTransition(
performance: _performance.view, performance: performance,
color: new AnimatedColorValue(Colors.transparent, end: Colors.black54), color: new AnimatedColorValue(Colors.transparent, end: Colors.black54),
child: new Container() child: new Container()
) )
); );
Widget content = new SlideTransition( Widget content = new SlideTransition(
performance: _performance.view, performance: performance,
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: _kThemeChangeDuration, duration: _kThemeChangeDuration,
decoration: new BoxDecoration( decoration: new BoxDecoration(
backgroundColor: Theme.of(context).canvasColor, backgroundColor: Theme.of(context).canvasColor,
boxShadow: shadows[config.level]), boxShadow: shadows[level]),
width: _kWidth, width: _kWidth,
child: config.child child: child
) )
); );
return new GestureDetector( return new Stack([
onHorizontalDragStart: _performance.stop,
onHorizontalDragUpdate: _handleDragUpdate,
onHorizontalDragEnd: _handleDragEnd,
child: new Stack([
mask, mask,
new Positioned( new Positioned(
top: 0.0, top: 0.0,
...@@ -98,56 +80,68 @@ class DrawerState extends State<Drawer> { ...@@ -98,56 +80,68 @@ class DrawerState extends State<Drawer> {
bottom: 0.0, bottom: 0.0,
child: content child: content
) )
]) ]);
);
}
bool get _isMostlyClosed => _performance.progress < 0.5;
void _handleDragUpdate(double delta) {
_performance.progress += delta / _kWidth;
}
void _open() {
_performance.fling(velocity: 1.0);
}
void _close() {
_performance.fling(velocity: -1.0);
}
void _handleDragEnd(Offset velocity) {
if (velocity.dx.abs() >= _kMinFlingVelocity) {
_performance.fling(velocity: velocity.dx * _kFlingVelocityScale);
} else if (_isMostlyClosed) {
_close();
} else {
_open();
}
} }
} }
class DrawerRoute extends Route { class _DrawerRoute extends Route {
DrawerRoute({ this.child, this.level }); _DrawerRoute({ this.child, this.level });
final Widget child; final Widget child;
final int level; final int level;
PerformanceView get performance => _performance?.view;
Performance _performance = new Performance(duration: _kBaseSettleDuration);
bool get opaque => false; bool get opaque => false;
Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) { Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) {
return new Focus( return new Focus(
key: new GlobalObjectKey(this), key: new GlobalObjectKey(this),
autofocus: true, autofocus: true,
child: new Drawer( child: new GestureDetector(
onHorizontalDragStart: () {
_performance?.stop();
},
onHorizontalDragUpdate: (double delta) {
_performance?.progress = delta / _kWidth;
},
onHorizontalDragEnd: _settle,
child: new _Drawer(
child: child, child: child,
level: level, level: level,
navigator: navigator performance: performance
)
) )
); );
} }
void didPush(NavigatorState navigator) {
super.didPush(navigator);
_performance.forward();
}
void didPop([dynamic result]) {
super.didPop(result);
_performance.reverse();
_performance = null;
}
void _settle(Offset velocity) {
if (velocity.dx.abs() >= _kMinFlingVelocity) {
_performance?.fling(velocity: velocity.dx * _kFlingVelocityScale);
} else if (_performance?.progress < 0.5) {
close();
} else {
_performance?.fling(velocity: 1.0);
}
}
void close() {
_performance?.fling(velocity: -1.0);
}
} }
void showDrawer({ NavigatorState navigator, Widget child, int level: 3 }) { void showDrawer({ NavigatorState navigator, Widget child, int level: 3 }) {
navigator.push(new DrawerRoute(child: child, level: level)); 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