Some clean-up of the Heroes code (#9428)
This commit is contained in:
parent
71d80fbd3f
commit
a6a8d997a3
@ -28,7 +28,7 @@ enum _HeroFlightType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The bounding box for context in global coordinates.
|
// The bounding box for context in global coordinates.
|
||||||
Rect _globalRect(BuildContext context) {
|
Rect _globalBoundingBoxFor(BuildContext context) {
|
||||||
final RenderBox box = context.findRenderObject();
|
final RenderBox box = context.findRenderObject();
|
||||||
assert(box != null && box.hasSize);
|
assert(box != null && box.hasSize);
|
||||||
return MatrixUtils.transformRect(box.getTransformTo(null), Offset.zero & box.size);
|
return MatrixUtils.transformRect(box.getTransformTo(null), Offset.zero & box.size);
|
||||||
@ -170,7 +170,7 @@ class _HeroState extends State<Hero> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything known about a hero flight that's to be started or restarted.
|
// Everything known about a hero flight that's to be started or diverted.
|
||||||
class _HeroFlightManifest {
|
class _HeroFlightManifest {
|
||||||
_HeroFlightManifest({
|
_HeroFlightManifest({
|
||||||
@required this.type,
|
@required this.type,
|
||||||
@ -317,9 +317,9 @@ class _HeroFlight {
|
|||||||
manifest.fromHero.startFlight();
|
manifest.fromHero.startFlight();
|
||||||
manifest.toHero.startFlight();
|
manifest.toHero.startFlight();
|
||||||
|
|
||||||
heroRect = new RectTween(
|
heroRect = _doCreateRectTween(
|
||||||
begin: _globalRect(manifest.fromHero.context),
|
_globalBoundingBoxFor(manifest.fromHero.context),
|
||||||
end: _globalRect(manifest.toHero.context),
|
_globalBoundingBoxFor(manifest.toHero.context),
|
||||||
);
|
);
|
||||||
|
|
||||||
overlayEntry = new OverlayEntry(builder: _buildOverlay);
|
overlayEntry = new OverlayEntry(builder: _buildOverlay);
|
||||||
@ -328,7 +328,7 @@ class _HeroFlight {
|
|||||||
|
|
||||||
// While this flight's hero was in transition a push or a pop occurred for
|
// While this flight's hero was in transition a push or a pop occurred for
|
||||||
// routes with the same hero. Redirect the in-flight hero to the new toRoute.
|
// routes with the same hero. Redirect the in-flight hero to the new toRoute.
|
||||||
void restart(_HeroFlightManifest newManifest) {
|
void divert(_HeroFlightManifest newManifest) {
|
||||||
assert(manifest.tag == newManifest.tag);
|
assert(manifest.tag == newManifest.tag);
|
||||||
|
|
||||||
if (manifest.type == _HeroFlightType.push && newManifest.type == _HeroFlightType.pop) {
|
if (manifest.type == _HeroFlightType.push && newManifest.type == _HeroFlightType.pop) {
|
||||||
@ -341,10 +341,7 @@ class _HeroFlight {
|
|||||||
|
|
||||||
_proxyAnimation.parent = new ReverseAnimation(newManifest.animation);
|
_proxyAnimation.parent = new ReverseAnimation(newManifest.animation);
|
||||||
|
|
||||||
heroRect = new RectTween(
|
heroRect = _doCreateRectTween(heroRect.end, heroRect.begin);
|
||||||
begin: heroRect.end,
|
|
||||||
end: heroRect.begin,
|
|
||||||
);
|
|
||||||
} else if (manifest.type == _HeroFlightType.pop && newManifest.type == _HeroFlightType.push) {
|
} else if (manifest.type == _HeroFlightType.pop && newManifest.type == _HeroFlightType.push) {
|
||||||
// A pop flight was interrupted by a push.
|
// A pop flight was interrupted by a push.
|
||||||
assert(newManifest.animation.status == AnimationStatus.forward);
|
assert(newManifest.animation.status == AnimationStatus.forward);
|
||||||
@ -359,15 +356,9 @@ class _HeroFlight {
|
|||||||
if (manifest.fromHero != newManifest.toHero) {
|
if (manifest.fromHero != newManifest.toHero) {
|
||||||
manifest.fromHero.endFlight();
|
manifest.fromHero.endFlight();
|
||||||
newManifest.toHero.startFlight();
|
newManifest.toHero.startFlight();
|
||||||
heroRect = new RectTween(
|
heroRect = _doCreateRectTween(heroRect.end, _globalBoundingBoxFor(newManifest.toHero.context));
|
||||||
begin: heroRect.end,
|
|
||||||
end: _globalRect(newManifest.toHero.context),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
heroRect = new RectTween(
|
heroRect = _doCreateRectTween(heroRect.end, heroRect.begin);
|
||||||
begin: heroRect.end,
|
|
||||||
end: heroRect.begin,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// A push or a pop flight is heading to a new route, i.e.
|
// A push or a pop flight is heading to a new route, i.e.
|
||||||
@ -376,10 +367,7 @@ class _HeroFlight {
|
|||||||
assert(manifest.fromHero != newManifest.fromHero);
|
assert(manifest.fromHero != newManifest.fromHero);
|
||||||
assert(manifest.toHero != newManifest.toHero);
|
assert(manifest.toHero != newManifest.toHero);
|
||||||
|
|
||||||
heroRect = new RectTween(
|
heroRect = _doCreateRectTween(heroRect.evaluate(_proxyAnimation), _globalBoundingBoxFor(newManifest.toHero.context));
|
||||||
begin: heroRect.evaluate(_proxyAnimation),
|
|
||||||
end: _globalRect(newManifest.toHero.context),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (newManifest.type == _HeroFlightType.pop)
|
if (newManifest.type == _HeroFlightType.pop)
|
||||||
_proxyAnimation.parent = new ReverseAnimation(newManifest.animation);
|
_proxyAnimation.parent = new ReverseAnimation(newManifest.animation);
|
||||||
@ -464,39 +452,38 @@ class HeroController extends NavigatorObserver {
|
|||||||
final PageRoute<dynamic> to = toRoute;
|
final PageRoute<dynamic> to = toRoute;
|
||||||
final Animation<double> animation = (flightType == _HeroFlightType.push) ? to.animation : from.animation;
|
final Animation<double> animation = (flightType == _HeroFlightType.push) ? to.animation : from.animation;
|
||||||
|
|
||||||
// A "user" gesture may have already completed the pop.
|
// A user gesture may have already completed the pop.
|
||||||
if (flightType == _HeroFlightType.pop && animation.status == AnimationStatus.dismissed)
|
if (flightType == _HeroFlightType.pop && animation.status == AnimationStatus.dismissed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Putting a route offstage changes its animation value to 1.0.
|
// Putting a route offstage changes its animation value to 1.0. Once this
|
||||||
// Once this frame completes, we'll know where the heroes in the toRoute
|
// frame completes, we'll know where the heroes in the `to` route are
|
||||||
// are going to end up, and the toRoute will go back on stage.
|
// going to end up, and the `to` route will go back onstage.
|
||||||
to.offstage = animation.value == 0.0 || animation.value == 1.0;
|
to.offstage = to.animation.value == 0.0;
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((Duration _) {
|
WidgetsBinding.instance.addPostFrameCallback((Duration value) {
|
||||||
_startHeroTransition(from, to, flightType);
|
_startHeroTransition(from, to, flightType);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the matching pairs of heros in from and to and either start or a new
|
// Find the matching pairs of heros in from and to and either start or a new
|
||||||
// hero flight, or restart an existing one.
|
// hero flight, or divert an existing one.
|
||||||
void _startHeroTransition(PageRoute<dynamic> from, PageRoute<dynamic> to, _HeroFlightType flightType) {
|
void _startHeroTransition(PageRoute<dynamic> from, PageRoute<dynamic> to, _HeroFlightType flightType) {
|
||||||
// The navigator or one of the routes subtrees was removed before this
|
// If the navigator or one of the routes subtrees was removed before this
|
||||||
// end-of-frame callback was called then don't actually start a transition.
|
// end-of-frame callback was called, then don't actually start a transition.
|
||||||
// TBD: need to generate tests for these cases
|
|
||||||
if (navigator == null || from.subtreeContext == null || to.subtreeContext == null) {
|
if (navigator == null || from.subtreeContext == null || to.subtreeContext == null) {
|
||||||
to.offstage = false; // TBD: only do this if to.subtreeContext != null?
|
to.offstage = false; // in case we set this in _maybeStartHeroTransition
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Rect navigatorRect = _globalRect(navigator.context);
|
final Rect navigatorRect = _globalBoundingBoxFor(navigator.context);
|
||||||
|
|
||||||
// At this point the toHeroes may have been built and laid out for the first time.
|
// At this point the toHeroes may have been built and laid out for the first time.
|
||||||
final Map<Object, _HeroState> fromHeroes = Hero._allHeroesFor(from.subtreeContext);
|
final Map<Object, _HeroState> fromHeroes = Hero._allHeroesFor(from.subtreeContext);
|
||||||
final Map<Object, _HeroState> toHeroes = Hero._allHeroesFor(to.subtreeContext);
|
final Map<Object, _HeroState> toHeroes = Hero._allHeroesFor(to.subtreeContext);
|
||||||
|
|
||||||
// If the to route was offstage, then we're implicitly restoring its
|
// If the `to` route was offstage, then we're implicitly restoring its
|
||||||
// animation value back to what it was before it was "moved" offstage.
|
// animation value back to what it was before it was "moved" offstage.
|
||||||
to.offstage = false;
|
to.offstage = false;
|
||||||
|
|
||||||
@ -512,9 +499,8 @@ class HeroController extends NavigatorObserver {
|
|||||||
toHero: toHeroes[tag],
|
toHero: toHeroes[tag],
|
||||||
createRectTween: createRectTween,
|
createRectTween: createRectTween,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_flights[tag] != null)
|
if (_flights[tag] != null)
|
||||||
_flights[tag].restart(manifest);
|
_flights[tag].divert(manifest);
|
||||||
else
|
else
|
||||||
_flights[tag] = new _HeroFlight(_handleFlightEnded)..start(manifest);
|
_flights[tag] = new _HeroFlight(_handleFlightEnded)..start(manifest);
|
||||||
} else if (_flights[tag] != null) {
|
} else if (_flights[tag] != null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user