@@ -19,7 +19,7 @@ interface TransitionListener {
1919 new ( entry : ExpandedEntry , transition : android . transition . Transition ) : ExpandedTransitionListener ;
2020}
2121
22- interface ExpandedAnimation extends android . view . animation . Animation {
22+ interface ExpandedAnimator extends android . animation . Animator {
2323 entry : ExpandedEntry ;
2424 transitionType ?: string ;
2525}
@@ -35,27 +35,28 @@ interface ExpandedEntry extends BackstackEntry {
3535 reenterTransitionListener : ExpandedTransitionListener ;
3636 returnTransitionListener : ExpandedTransitionListener ;
3737
38- enterAnimation : ExpandedAnimation ;
39- exitAnimation : ExpandedAnimation ;
40- popEnterAnimation : ExpandedAnimation ;
41- popExitAnimation : ExpandedAnimation ;
38+ enterAnimator : ExpandedAnimator ;
39+ exitAnimator : ExpandedAnimator ;
40+ popEnterAnimator : ExpandedAnimator ;
41+ popExitAnimator : ExpandedAnimator ;
4242
43- defaultEnterAnimation : ExpandedAnimation ;
44- defaultExitAnimation : ExpandedAnimation ;
43+ defaultEnterAnimator : ExpandedAnimator ;
44+ defaultExitAnimator : ExpandedAnimator ;
4545
4646 transition : Transition ;
4747 transitionName : string ;
4848 frameId : number
4949}
5050
5151const sdkVersion = lazy ( ( ) => parseInt ( device . sdkVersion ) ) ;
52+ const intEvaluator = lazy ( ( ) => new android . animation . IntEvaluator ( ) ) ;
5253const defaultInterpolator = lazy ( ( ) => new android . view . animation . AccelerateDecelerateInterpolator ( ) ) ;
5354
5455export const waitingQueue = new Map < number , Set < ExpandedEntry > > ( ) ;
5556export const completedEntries = new Map < number , ExpandedEntry > ( ) ;
5657
5758let TransitionListener : TransitionListener ;
58- let AnimationListener : android . view . animation . Animation . AnimationListener ;
59+ let AnimationListener : android . animation . Animator . AnimatorListener ;
5960
6061export function _setAndroidFragmentTransitions (
6162 animated : boolean ,
@@ -170,39 +171,39 @@ export function _setAndroidFragmentTransitions(
170171 printTransitions ( newEntry ) ;
171172}
172173
173- export function _onFragmentCreateAnimation ( entry : ExpandedEntry , fragment : android . support . v4 . app . Fragment , nextAnim : number , enter : boolean ) : android . view . animation . Animation {
174- let animation : android . view . animation . Animation ;
174+ export function _onFragmentCreateAnimator ( entry : ExpandedEntry , fragment : android . support . v4 . app . Fragment , nextAnim : number , enter : boolean ) : android . animation . Animator {
175+ let animator : android . animation . Animator ;
175176 switch ( nextAnim ) {
176177 case AnimationType . enterFakeResourceId :
177- animation = entry . enterAnimation ;
178+ animator = entry . enterAnimator ;
178179 break ;
179180
180181 case AnimationType . exitFakeResourceId :
181- animation = entry . exitAnimation ;
182+ animator = entry . exitAnimator ;
182183 break ;
183184
184185 case AnimationType . popEnterFakeResourceId :
185- animation = entry . popEnterAnimation ;
186+ animator = entry . popEnterAnimator ;
186187 break ;
187188
188189 case AnimationType . popExitFakeResourceId :
189- animation = entry . popExitAnimation ;
190+ animator = entry . popExitAnimator ;
190191 break ;
191192 }
192193
193- if ( ! animation && sdkVersion ( ) >= 21 ) {
194+ if ( ! animator && sdkVersion ( ) >= 21 ) {
194195 const view = fragment . getView ( ) ;
195196 const jsParent = entry . resolvedPage . parent ;
196197 const parent = view . getParent ( ) || ( jsParent && jsParent . nativeViewProtected ) ;
197198 const animatedEntries = _getAnimatedEntries ( entry . frameId ) ;
198199 if ( ! animatedEntries || ! animatedEntries . has ( entry ) ) {
199200 if ( parent && ! ( < any > parent ) . isLaidOut ( ) ) {
200- animation = enter ? entry . defaultEnterAnimation : entry . defaultExitAnimation ;
201+ animator = enter ? entry . defaultEnterAnimator : entry . defaultExitAnimator ;
201202 }
202203 }
203204 }
204205
205- return animation ;
206+ return animator ;
206207}
207208
208209export function _getAnimatedEntries ( frameId : number ) : Set < BackstackEntry > {
@@ -312,40 +313,40 @@ function getTransitionListener(entry: ExpandedEntry, transition: android.transit
312313 return new TransitionListener ( entry , transition ) ;
313314}
314315
315- function getAnimationListener ( ) : android . view . animation . Animation . AnimationListener {
316+ function getAnimationListener ( ) : android . animation . Animator . AnimatorListener {
316317 if ( ! AnimationListener ) {
317- @Interfaces ( [ android . view . animation . Animation . AnimationListener ] )
318- class AnimationListenerImpl extends java . lang . Object implements android . view . animation . Animation . AnimationListener {
318+ @Interfaces ( [ android . animation . Animator . AnimatorListener ] )
319+ class AnimationListenerImpl extends java . lang . Object implements android . animation . Animator . AnimatorListener {
319320 constructor ( ) {
320321 super ( ) ;
321322 return global . __native ( this ) ;
322323 }
323324
324- onAnimationStart ( animation : ExpandedAnimation ) : void {
325- const entry = animation . entry ;
325+ onAnimationStart ( animator : ExpandedAnimator ) : void {
326+ const entry = animator . entry ;
326327 addToWaitingQueue ( entry ) ;
327328 if ( traceEnabled ( ) ) {
328- traceWrite ( `START ${ animation . transitionType } for ${ entry . fragmentTag } ` , traceCategories . Transition ) ;
329+ traceWrite ( `START ${ animator . transitionType } for ${ entry . fragmentTag } ` , traceCategories . Transition ) ;
329330 }
330331 }
331332
332- onAnimationRepeat ( animation : ExpandedAnimation ) : void {
333+ onAnimationRepeat ( animator : ExpandedAnimator ) : void {
333334 if ( traceEnabled ( ) ) {
334- traceWrite ( `REPEAT ${ animation . transitionType } for ${ animation . entry . fragmentTag } ` , traceCategories . Transition ) ;
335+ traceWrite ( `REPEAT ${ animator . transitionType } for ${ animator . entry . fragmentTag } ` , traceCategories . Transition ) ;
335336 }
336337 }
337338
338- onAnimationEnd ( animation : ExpandedAnimation ) : void {
339+ onAnimationEnd ( animator : ExpandedAnimator ) : void {
339340 if ( traceEnabled ( ) ) {
340- traceWrite ( `END ${ animation . transitionType } for ${ animation . entry . fragmentTag } ` , traceCategories . Transition ) ;
341+ traceWrite ( `END ${ animator . transitionType } for ${ animator . entry . fragmentTag } ` , traceCategories . Transition ) ;
341342 }
342343
343- transitionOrAnimationCompleted ( animation . entry ) ;
344+ transitionOrAnimationCompleted ( animator . entry ) ;
344345 }
345346
346- onAnimationCancel ( animation : ExpandedAnimation ) : void {
347+ onAnimationCancel ( animator : ExpandedAnimator ) : void {
347348 if ( traceEnabled ( ) ) {
348- traceWrite ( `CANCEL ${ animation . transitionType } for ${ animation . entry . fragmentTag } ` , traceCategories . Transition ) ;
349+ traceWrite ( `CANCEL ${ animator . transitionType } for ${ animator . entry . fragmentTag } ` , traceCategories . Transition ) ;
349350 }
350351 }
351352 }
@@ -367,18 +368,19 @@ function addToWaitingQueue(entry: ExpandedEntry): void {
367368 entries . add ( entry ) ;
368369}
369370
370- function clearAnimationListener ( animation : ExpandedAnimation ) : void {
371- if ( ! animation ) {
371+ function clearAnimationListener ( animator : ExpandedAnimator , listener : android . animation . Animator . AnimatorListener ) : void {
372+ if ( ! animator ) {
372373 return ;
373374 }
374375
376+ animator . removeListener ( listener ) ;
377+
375378 if ( traceEnabled ( ) ) {
376- const entry = animation . entry ;
377- traceWrite ( `Clear ${ animation . transitionType } - ${ entry . transition } for ${ entry . fragmentTag } ` , traceCategories . Transition ) ;
379+ const entry = animator . entry ;
380+ traceWrite ( `Clear ${ animator . transitionType } - ${ entry . transition } for ${ entry . fragmentTag } ` , traceCategories . Transition ) ;
378381 }
379382
380- animation . setAnimationListener ( null ) ;
381- animation . entry = null ;
383+ animator . entry = null ;
382384}
383385
384386function clearExitAndReenterTransitions ( entry : ExpandedEntry , removeListener : boolean ) : void {
@@ -477,10 +479,11 @@ function clearEntry(entry: ExpandedEntry, removeListener: boolean): void {
477479 }
478480
479481 if ( removeListener ) {
480- clearAnimationListener ( entry . enterAnimation ) ;
481- clearAnimationListener ( entry . exitAnimation ) ;
482- clearAnimationListener ( entry . popEnterAnimation ) ;
483- clearAnimationListener ( entry . popExitAnimation ) ;
482+ const listener = getAnimationListener ( ) ;
483+ clearAnimationListener ( entry . enterAnimator , listener ) ;
484+ clearAnimationListener ( entry . exitAnimator , listener ) ;
485+ clearAnimationListener ( entry . popEnterAnimator , listener ) ;
486+ clearAnimationListener ( entry . popExitAnimator , listener ) ;
484487 }
485488}
486489
@@ -617,21 +620,21 @@ function setupNewFragmentExplodeTransition(navTransition: NavigationTransition,
617620function setupExitAndPopEnterAnimation ( entry : ExpandedEntry , transition : Transition ) : void {
618621 const listener = getAnimationListener ( ) ;
619622
620- // remove previous listener if we are changing the animation .
621- clearAnimationListener ( entry . exitAnimation ) ;
622- clearAnimationListener ( entry . popEnterAnimation ) ;
623+ // remove previous listener if we are changing the animator .
624+ clearAnimationListener ( entry . exitAnimator , listener ) ;
625+ clearAnimationListener ( entry . popEnterAnimator , listener ) ;
623626
624- const exitAnimation = < ExpandedAnimation > transition . createAndroidAnimation ( AndroidTransitionType . exit ) ;
625- exitAnimation . transitionType = AndroidTransitionType . exit ;
626- exitAnimation . entry = entry ;
627- exitAnimation . setAnimationListener ( listener ) ;
628- entry . exitAnimation = exitAnimation ;
627+ const exitAnimator = < ExpandedAnimator > transition . createAndroidAnimator ( AndroidTransitionType . exit ) ;
628+ exitAnimator . transitionType = AndroidTransitionType . exit ;
629+ exitAnimator . entry = entry ;
630+ exitAnimator . addListener ( listener ) ;
631+ entry . exitAnimator = exitAnimator ;
629632
630- const popEnterAnimation = < ExpandedAnimation > transition . createAndroidAnimation ( AndroidTransitionType . popEnter ) ;
631- popEnterAnimation . transitionType = AndroidTransitionType . popEnter ;
632- popEnterAnimation . entry = entry ;
633- popEnterAnimation . setAnimationListener ( listener ) ;
634- entry . popEnterAnimation = popEnterAnimation ;
633+ const popEnterAnimator = < ExpandedAnimator > transition . createAndroidAnimator ( AndroidTransitionType . popEnter ) ;
634+ popEnterAnimator . transitionType = AndroidTransitionType . popEnter ;
635+ popEnterAnimator . entry = entry ;
636+ popEnterAnimator . addListener ( listener ) ;
637+ entry . popEnterAnimator = popEnterAnimator ;
635638}
636639
637640function setupAllAnimation ( entry : ExpandedEntry , transition : Transition ) : void {
@@ -640,33 +643,33 @@ function setupAllAnimation(entry: ExpandedEntry, transition: Transition): void {
640643
641644 // setupAllAnimation is called only for new fragments so we don't
642645 // need to clearAnimationListener for enter & popExit animators.
643- const enterAnimation = < ExpandedAnimation > transition . createAndroidAnimation ( AndroidTransitionType . enter ) ;
644- enterAnimation . transitionType = AndroidTransitionType . enter ;
645- enterAnimation . entry = entry ;
646- enterAnimation . setAnimationListener ( listener ) ;
647- entry . enterAnimation = enterAnimation ;
646+ const enterAnimator = < ExpandedAnimator > transition . createAndroidAnimator ( AndroidTransitionType . enter ) ;
647+ enterAnimator . transitionType = AndroidTransitionType . enter ;
648+ enterAnimator . entry = entry ;
649+ enterAnimator . addListener ( listener ) ;
650+ entry . enterAnimator = enterAnimator ;
648651
649- const popExitAnimation = < ExpandedAnimation > transition . createAndroidAnimation ( AndroidTransitionType . popExit ) ;
650- popExitAnimation . transitionType = AndroidTransitionType . popExit ;
651- popExitAnimation . entry = entry ;
652- popExitAnimation . setAnimationListener ( listener ) ;
653- entry . popExitAnimation = popExitAnimation ;
652+ const popExitAnimator = < ExpandedAnimator > transition . createAndroidAnimator ( AndroidTransitionType . popExit ) ;
653+ popExitAnimator . transitionType = AndroidTransitionType . popExit ;
654+ popExitAnimator . entry = entry ;
655+ popExitAnimator . addListener ( listener ) ;
656+ entry . popExitAnimator = popExitAnimator ;
654657}
655658
656659function setupDefaultAnimations ( entry : ExpandedEntry , transition : Transition ) : void {
657660 const listener = getAnimationListener ( ) ;
658661
659- const enterAnimation = < ExpandedAnimation > transition . createAndroidAnimation ( AndroidTransitionType . enter ) ;
660- enterAnimation . transitionType = AndroidTransitionType . enter ;
661- enterAnimation . entry = entry ;
662- enterAnimation . setAnimationListener ( listener ) ;
663- entry . defaultEnterAnimation = enterAnimation ;
662+ const enterAnimator = < ExpandedAnimator > transition . createAndroidAnimator ( AndroidTransitionType . enter ) ;
663+ enterAnimator . transitionType = AndroidTransitionType . enter ;
664+ enterAnimator . entry = entry ;
665+ enterAnimator . addListener ( listener ) ;
666+ entry . defaultEnterAnimator = enterAnimator ;
664667
665- const exitAnimation = < ExpandedAnimation > transition . createAndroidAnimation ( AndroidTransitionType . exit ) ;
666- exitAnimation . transitionType = AndroidTransitionType . exit ;
667- exitAnimation . entry = entry ;
668- exitAnimation . setAnimationListener ( listener ) ;
669- entry . defaultExitAnimation = exitAnimation ;
668+ const exitAnimator = < ExpandedAnimator > transition . createAndroidAnimator ( AndroidTransitionType . exit ) ;
669+ exitAnimator . transitionType = AndroidTransitionType . exit ;
670+ exitAnimator . entry = entry ;
671+ exitAnimator . addListener ( listener ) ;
672+ entry . defaultExitAnimator = exitAnimator ;
670673}
671674
672675function setUpNativeTransition ( navigationTransition : NavigationTransition , nativeTransition : android . transition . Transition ) {
@@ -729,10 +732,10 @@ function printTransitions(entry: ExpandedEntry) {
729732 }
730733
731734 if ( entry . transition ) {
732- result += `enterAnimator=${ entry . enterAnimation } , ` ;
733- result += `exitAnimator=${ entry . exitAnimation } , ` ;
734- result += `popEnterAnimator=${ entry . popEnterAnimation } , ` ;
735- result += `popExitAnimator=${ entry . popExitAnimation } , ` ;
735+ result += `enterAnimator=${ entry . enterAnimator } , ` ;
736+ result += `exitAnimator=${ entry . exitAnimator } , ` ;
737+ result += `popEnterAnimator=${ entry . popEnterAnimator } , ` ;
738+ result += `popExitAnimator=${ entry . popExitAnimator } , ` ;
736739 }
737740 if ( sdkVersion ( ) >= 21 ) {
738741 const fragment = entry . fragment ;
@@ -745,16 +748,20 @@ function printTransitions(entry: ExpandedEntry) {
745748 }
746749}
747750
751+ function javaObjectArray ( ...params : java . lang . Object [ ] ) {
752+ const nativeArray = Array . create ( java . lang . Object , params . length ) ;
753+ params . forEach ( ( value , i ) => nativeArray [ i ] = value ) ;
754+ return nativeArray ;
755+ }
756+
757+ function createDummyZeroDurationAnimator ( ) : android . animation . Animator {
758+ const animator = android . animation . ValueAnimator . ofObject ( intEvaluator ( ) , javaObjectArray ( java . lang . Integer . valueOf ( 0 ) , java . lang . Integer . valueOf ( 1 ) ) ) ;
759+ animator . setDuration ( 0 ) ;
760+ return animator ;
761+ }
762+
748763class NoTransition extends Transition {
749- public createAndroidAnimation ( transitionType : string ) : android . view . animation . Animation {
750- const animation = new android . view . animation . AlphaAnimation ( 1 , 1 ) ;
751- // NOTE: this should not be necessary when we revert to Animators API
752- // HACK: Android view animation with zero duration seems to be buggy and raises animation listener events in illogical (wrong?) order:
753- // "enter" start -> "enter" end -> "exit" start -> "exit" end;
754- // we would expect events to overlap "exit" start -> "enter" start -> "exit" end -> "enter" end, or at least
755- // "exit" start / end to be raised before "enter" start / end
756- animation . setDuration ( 1 ) ;
757-
758- return animation ;
764+ public createAndroidAnimator ( transitionType : string ) : android . animation . Animator {
765+ return createDummyZeroDurationAnimator ( ) ;
759766 }
760767}
0 commit comments