Commit 8cce992f authored by Hixie's avatar Hixie

Heroes: Pass next Performance to route builders

This is step 1 in making it possible to have hero transitions between
routes. To make it possible for a route to have an "exit" animation when
a new route has been pushed on top of it, we provide the next route's
AnimationPerformance to the build function. It's null if there is no
next route or if the next route has no performance.
parent fbd5460b
......@@ -899,6 +899,9 @@ class IgnorePointer extends OneChildRenderObjectWidget {
}
}
// UTILITY NODES
class MetaData extends OneChildRenderObjectWidget {
MetaData({ Key key, Widget child, this.metaData })
: super(key: key, child: child);
......@@ -911,3 +914,12 @@ class MetaData extends OneChildRenderObjectWidget {
renderObject.metaData = metaData;
}
}
class KeyedSubtree extends StatelessComponent {
KeyedSubtree({ Key key, this.child })
: super(key: key);
final Widget child;
Widget build(BuildContext context) => child;
}
\ No newline at end of file
......@@ -140,7 +140,7 @@ class DialogRoute extends Route {
Duration get transitionDuration => _kTransitionDuration;
bool get opaque => false;
Widget build(Key key, NavigatorState navigator) {
Widget build(NavigatorState navigator, WatchableAnimationPerformance nextRoutePerformance) {
return new FadeTransition(
performance: performance,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: easeOut),
......
......@@ -5,6 +5,7 @@
import 'dart:collection';
import 'dart:sky' as sky;
import 'package:sky/animation.dart';
import 'package:sky/rendering.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/binding.dart';
......@@ -199,10 +200,10 @@ class DragRoute extends Route {
bool get ephemeral => true;
bool get modal => false;
Duration get transitionDuration => const Duration();
bool get opaque => false;
Widget build(Key key, NavigatorState navigator) {
Duration get transitionDuration => const Duration();
Widget build(NavigatorState navigator, WatchableAnimationPerformance nextRoutePerformance) {
return new Positioned(
left: _lastOffset.dx,
top: _lastOffset.dy,
......
......@@ -118,6 +118,7 @@ class NavigatorState extends State<Navigator> {
Widget build(BuildContext context) {
List<Widget> visibleRoutes = new List<Widget>();
bool alreadyInsertModalBarrier = false;
WatchableAnimationPerformance nextPerformance;
for (int i = _history.length-1; i >= 0; i -= 1) {
Route route = _history[i];
if (!route.hasContent) {
......@@ -133,9 +134,12 @@ class NavigatorState extends State<Navigator> {
_history.remove(route);
});
};
Key key = new ObjectKey(route);
Widget widget = route.build(key, this);
visibleRoutes.add(widget);
visibleRoutes.add(
new KeyedSubtree(
key: new ObjectKey(route),
child: route.build(this, nextPerformance)
)
);
if (route.isActuallyOpaque)
break;
assert(route.modal || route.ephemeral);
......@@ -146,6 +150,7 @@ class NavigatorState extends State<Navigator> {
));
alreadyInsertModalBarrier = true;
}
nextPerformance = route.performance;
}
return new Focus(child: new Stack(visibleRoutes.reversed.toList()));
}
......@@ -238,7 +243,7 @@ abstract class Route {
bool get isActuallyOpaque => (performance == null || _performance.isCompleted) && opaque;
Widget build(Key key, NavigatorState navigator);
Widget build(NavigatorState navigator, WatchableAnimationPerformance nextRoutePerformance);
void didPop([dynamic result]) {
if (performance == null && _onDismissed != null)
_onDismissed();
......@@ -256,14 +261,12 @@ class PageRoute extends Route {
final RouteBuilder builder;
bool get opaque => true;
Duration get transitionDuration => _kTransitionDuration;
Widget build(Key key, NavigatorState navigator) {
Widget build(NavigatorState navigator, WatchableAnimationPerformance nextRoutePerformance) {
// TODO(jackson): Hit testing should ignore transform
// TODO(jackson): Block input unless content is interactive
return new SlideTransition(
key: key,
performance: performance,
position: new AnimatedValue<Point>(_kTransitionStartPoint, end: Point.origin, curve: easeOut),
child: new FadeTransition(
......@@ -293,5 +296,5 @@ class RouteState extends Route {
super.didPop(result);
}
Widget build(Key key, NavigatorState navigator) => null;
Widget build(NavigatorState navigator, WatchableAnimationPerformance nextRoutePerformance) => null;
}
......@@ -169,10 +169,10 @@ class MenuRoute extends Route {
bool get ephemeral => false; // we could make this true, but then we'd have to use popRoute(), not pop(), in menus
bool get modal => true;
Duration get transitionDuration => _kMenuDuration;
bool get opaque => false;
Widget build(Key key, NavigatorState navigator) {
Duration get transitionDuration => _kMenuDuration;
Widget build(NavigatorState navigator, WatchableAnimationPerformance nextRoutePerformance) {
return new Positioned(
top: position?.top,
right: position?.right,
......@@ -182,7 +182,6 @@ class MenuRoute extends Route {
key: new GlobalObjectKey(this),
autofocus: true,
child: new PopupMenu(
key: key,
items: builder != null ? builder(navigator) : const <PopupMenuItem>[],
level: level,
navigator: navigator,
......
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