Merge pull request #1500 from abarth/drawer_animate_back
The Drawer should animate out when popped off the navigator
This commit is contained in:
commit
2da0eb9769
@ -34,120 +34,114 @@ 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,
|
mask,
|
||||||
onHorizontalDragUpdate: _handleDragUpdate,
|
new Positioned(
|
||||||
onHorizontalDragEnd: _handleDragEnd,
|
top: 0.0,
|
||||||
child: new Stack([
|
left: 0.0,
|
||||||
mask,
|
bottom: 0.0,
|
||||||
new Positioned(
|
child: content
|
||||||
top: 0.0,
|
)
|
||||||
left: 0.0,
|
]);
|
||||||
bottom: 0.0,
|
|
||||||
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(
|
||||||
child: child,
|
onHorizontalDragStart: () {
|
||||||
level: level,
|
_performance?.stop();
|
||||||
navigator: navigator
|
},
|
||||||
|
onHorizontalDragUpdate: (double delta) {
|
||||||
|
_performance?.progress = delta / _kWidth;
|
||||||
|
},
|
||||||
|
onHorizontalDragEnd: _settle,
|
||||||
|
child: new _Drawer(
|
||||||
|
child: child,
|
||||||
|
level: level,
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user