@@ -293,85 +293,73 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
293293 final VoidCallback ? previousTrainHoppingListenerRemover = _trainHoppingListenerRemover;
294294 _trainHoppingListenerRemover = null ;
295295
296- if (nextRoute is TransitionRoute <dynamic >) {
297- if (canTransitionTo (nextRoute) && nextRoute.canTransitionFrom (this )) {
298- final Animation <double >? current = _secondaryAnimation.parent;
299- if (current != null ) {
300- final Animation <double > currentTrain = (current is TrainHoppingAnimation ? current.currentTrain : current)! ;
301- final Animation <double > nextTrain = nextRoute._animation! ;
302- if (
303- currentTrain.value == nextTrain.value ||
304- nextTrain.status == AnimationStatus .completed ||
305- nextTrain.status == AnimationStatus .dismissed
306- ) {
307- _setSecondaryAnimation (nextTrain, nextRoute.completed);
308- } else {
309- // Two trains animate at different values. We have to do train hopping.
310- // There are three possibilities of train hopping:
311- // 1. We hop on the nextTrain when two trains meet in the middle using
312- // TrainHoppingAnimation.
313- // 2. There is no chance to hop on nextTrain because two trains never
314- // cross each other. We have to directly set the animation to
315- // nextTrain once the nextTrain stops animating.
316- // 3. A new _updateSecondaryAnimation is called before train hopping
317- // finishes. We leave a listener remover for the next call to
318- // properly clean up the existing train hopping.
319- TrainHoppingAnimation ? newAnimation;
320- void jumpOnAnimationEnd (AnimationStatus status) {
321- switch (status) {
322- case AnimationStatus .completed:
323- case AnimationStatus .dismissed:
324- // The nextTrain has stopped animating without train hopping.
325- // Directly sets the secondary animation and disposes the
326- // TrainHoppingAnimation.
327- _setSecondaryAnimation (nextTrain, nextRoute.completed);
328- if (_trainHoppingListenerRemover != null ) {
329- _trainHoppingListenerRemover !();
330- _trainHoppingListenerRemover = null ;
331- }
332- break ;
333- case AnimationStatus .forward:
334- case AnimationStatus .reverse:
335- break ;
336- }
337- }
338- _trainHoppingListenerRemover = () {
339- nextTrain.removeStatusListener (jumpOnAnimationEnd);
340- newAnimation? .dispose ();
341- };
342- nextTrain.addStatusListener (jumpOnAnimationEnd);
343- newAnimation = TrainHoppingAnimation (
344- currentTrain,
345- nextTrain,
346- onSwitchedTrain: () {
347- assert (_secondaryAnimation.parent == newAnimation);
348- assert (newAnimation! .currentTrain == nextRoute._animation);
349- // We can hop on the nextTrain, so we don't need to listen to
350- // whether the nextTrain has stopped.
351- _setSecondaryAnimation (newAnimation! .currentTrain, nextRoute.completed);
296+ if (nextRoute is TransitionRoute <dynamic > && canTransitionTo (nextRoute) && nextRoute.canTransitionFrom (this )) {
297+ final Animation <double >? current = _secondaryAnimation.parent;
298+ if (current != null ) {
299+ final Animation <double > currentTrain = (current is TrainHoppingAnimation ? current.currentTrain : current)! ;
300+ final Animation <double > nextTrain = nextRoute._animation! ;
301+ if (
302+ currentTrain.value == nextTrain.value ||
303+ nextTrain.status == AnimationStatus .completed ||
304+ nextTrain.status == AnimationStatus .dismissed
305+ ) {
306+ _setSecondaryAnimation (nextTrain, nextRoute.completed);
307+ } else {
308+ // Two trains animate at different values. We have to do train hopping.
309+ // There are three possibilities of train hopping:
310+ // 1. We hop on the nextTrain when two trains meet in the middle using
311+ // TrainHoppingAnimation.
312+ // 2. There is no chance to hop on nextTrain because two trains never
313+ // cross each other. We have to directly set the animation to
314+ // nextTrain once the nextTrain stops animating.
315+ // 3. A new _updateSecondaryAnimation is called before train hopping
316+ // finishes. We leave a listener remover for the next call to
317+ // properly clean up the existing train hopping.
318+ TrainHoppingAnimation ? newAnimation;
319+ void jumpOnAnimationEnd (AnimationStatus status) {
320+ switch (status) {
321+ case AnimationStatus .completed:
322+ case AnimationStatus .dismissed:
323+ // The nextTrain has stopped animating without train hopping.
324+ // Directly sets the secondary animation and disposes the
325+ // TrainHoppingAnimation.
326+ _setSecondaryAnimation (nextTrain, nextRoute.completed);
352327 if (_trainHoppingListenerRemover != null ) {
353328 _trainHoppingListenerRemover !();
354329 _trainHoppingListenerRemover = null ;
355330 }
356- },
357- );
358- _setSecondaryAnimation (newAnimation, nextRoute.completed);
331+ break ;
332+ case AnimationStatus .forward:
333+ case AnimationStatus .reverse:
334+ break ;
335+ }
359336 }
360- } else { // This route has no secondary animation.
361- _setSecondaryAnimation (nextRoute._animation, nextRoute.completed);
337+ _trainHoppingListenerRemover = () {
338+ nextTrain.removeStatusListener (jumpOnAnimationEnd);
339+ newAnimation? .dispose ();
340+ };
341+ nextTrain.addStatusListener (jumpOnAnimationEnd);
342+ newAnimation = TrainHoppingAnimation (
343+ currentTrain,
344+ nextTrain,
345+ onSwitchedTrain: () {
346+ assert (_secondaryAnimation.parent == newAnimation);
347+ assert (newAnimation! .currentTrain == nextRoute._animation);
348+ // We can hop on the nextTrain, so we don't need to listen to
349+ // whether the nextTrain has stopped.
350+ _setSecondaryAnimation (newAnimation! .currentTrain, nextRoute.completed);
351+ if (_trainHoppingListenerRemover != null ) {
352+ _trainHoppingListenerRemover !();
353+ _trainHoppingListenerRemover = null ;
354+ }
355+ },
356+ );
357+ _setSecondaryAnimation (newAnimation, nextRoute.completed);
362358 }
363359 } else {
364- // This route cannot coordinate transitions with nextRoute, so it should
365- // have no visible secondary animation. By using an AnimationMin, the
366- // animation's value will always be zero, but it will have nextRoute.animation's
367- // status until it finishes, allowing this route to wait until all visible
368- // transitions are complete to stop ignoring pointers.
369- _setSecondaryAnimation (
370- AnimationMin <double >(kAlwaysDismissedAnimation, nextRoute._animation! ),
371- nextRoute.completed,
372- );
360+ _setSecondaryAnimation (nextRoute._animation, nextRoute.completed);
373361 }
374- } else { // The next route is not a TransitionRoute.
362+ } else {
375363 _setSecondaryAnimation (kAlwaysDismissedAnimation);
376364 }
377365 // Finally, we dispose any previous train hopping animation because it
@@ -408,9 +396,9 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
408396 /// the [nextRoute] is popped off of this route, the
409397 /// `secondaryAnimation` will run from 1.0 - 0.0.
410398 ///
411- /// If false, this route's [ModalRoute.buildTransitions] `secondaryAnimation`
412- /// will proxy an animation with a constant value of 0 . In other words, this
413- /// route will not animate when [nextRoute] is pushed on top of it or when
399+ /// If false, this route's [ModalRoute.buildTransitions] `secondaryAnimation` parameter
400+ /// value will be [kAlwaysDismissedAnimation] . In other words, this route
401+ /// will not animate when [nextRoute] is pushed on top of it or when
414402 /// [nextRoute] is popped off of it.
415403 ///
416404 /// Returns true by default.
@@ -858,19 +846,17 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
858846 context,
859847 widget.route.animation! ,
860848 widget.route.secondaryAnimation! ,
861- // _listenable updates when this route's animations change
862- // values, but the _ignorePointerNotifier can also update
863- // when the status of animations on popping routes change,
864- // even when this route's animations' values don't. Also,
865- // when the value of the _ignorePointerNotifier changes,
866- // it's only necessary to rebuild the IgnorePointer
867- // widget and set the focus node's ability to focus.
849+ // This additional AnimatedBuilder is include because if the
850+ // value of the userGestureInProgressNotifier changes, it's
851+ // only necessary to rebuild the IgnorePointer widget and set
852+ // the focus node's ability to focus.
868853 AnimatedBuilder (
869- animation: widget.route._ignorePointerNotifier ,
854+ animation: widget.route.navigator ? .userGestureInProgressNotifier ?? ValueNotifier < bool >( false ) ,
870855 builder: (BuildContext context, Widget ? child) {
871- focusScopeNode.canRequestFocus = ! _shouldIgnoreFocusRequest;
856+ final bool ignoreEvents = _shouldIgnoreFocusRequest;
857+ focusScopeNode.canRequestFocus = ! ignoreEvents;
872858 return IgnorePointer (
873- ignoring: widget.route._ignorePointer ,
859+ ignoring: ignoreEvents ,
874860 child: child,
875861 );
876862 },
@@ -1154,36 +1140,11 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
11541140 return child;
11551141 }
11561142
1157- /// Whether this route should ignore pointers when transitions are in progress.
1158- ///
1159- /// Pointers always are ignored when [isCurrent] is false (e.g., when a route
1160- /// has a new route pushed on top of it, or during a route's exit transition
1161- /// after popping). Override this value to also ignore pointers on pages during
1162- /// transitions where this route is the current route (e.g., after the route
1163- /// above this route pops, or during this route's entrance transition).
1164- ///
1165- /// Returns false by default.
1166- ///
1167- /// See also:
1168- ///
1169- /// * [CupertinoRouteTransitionMixin] , [CupertinoModalPopupRoute] , and
1170- /// [CupertinoDialogRoute], which use this property to specify that
1171- /// Cupertino routes ignore pointers during transitions.
1172- @protected
1173- bool get ignorePointerDuringTransitions => false ;
1174-
11751143 @override
11761144 void install () {
11771145 super .install ();
1178- _animationProxy = ProxyAnimation (super .animation)
1179- ..addStatusListener (_handleAnimationStatusChanged);
1180- _secondaryAnimationProxy = ProxyAnimation (super .secondaryAnimation)
1181- ..addStatusListener (_handleAnimationStatusChanged);
1182- navigator! .userGestureInProgressNotifier.addListener (_maybeUpdateIgnorePointer);
1183- }
1184-
1185- void _handleAnimationStatusChanged (AnimationStatus status) {
1186- _maybeUpdateIgnorePointer ();
1146+ _animationProxy = ProxyAnimation (super .animation);
1147+ _secondaryAnimationProxy = ProxyAnimation (super .secondaryAnimation);
11871148 }
11881149
11891150 @override
@@ -1419,19 +1380,6 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
14191380 Animation <double >? get secondaryAnimation => _secondaryAnimationProxy;
14201381 ProxyAnimation ? _secondaryAnimationProxy;
14211382
1422- bool get _ignorePointer => _ignorePointerNotifier.value;
1423- final ValueNotifier <bool > _ignorePointerNotifier = ValueNotifier <bool >(false );
1424-
1425- void _maybeUpdateIgnorePointer () {
1426- bool isTransitioning (Animation <double >? animation) {
1427- return animation? .status == AnimationStatus .forward || animation? .status == AnimationStatus .reverse;
1428- }
1429- _ignorePointerNotifier.value = ! isCurrent ||
1430- (navigator? .userGestureInProgress ?? false ) ||
1431- (ignorePointerDuringTransitions &&
1432- (isTransitioning (animation) || isTransitioning (secondaryAnimation)));
1433- }
1434-
14351383 final List <WillPopCallback > _willPopCallbacks = < WillPopCallback > [];
14361384
14371385 /// Returns [RoutePopDisposition.doNotPop] if any of callbacks added with
@@ -1650,14 +1598,9 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
16501598 child: barrier,
16511599 );
16521600 }
1653- barrier = AnimatedBuilder (
1654- animation: _ignorePointerNotifier,
1655- builder: (BuildContext context, Widget ? child) {
1656- return IgnorePointer (
1657- ignoring: _ignorePointer,
1658- child: child,
1659- );
1660- },
1601+ barrier = IgnorePointer (
1602+ ignoring: animation! .status == AnimationStatus .reverse || // changedInternalState is called when animation.status updates
1603+ animation! .status == AnimationStatus .dismissed, // dismissed is possible when doing a manual pop gesture
16611604 child: barrier,
16621605 );
16631606 if (semanticsDismissible && barrierDismissible) {
0 commit comments