Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c8c0be7

Browse files
authored
refactor: restore animators api usage (NativeScript#6403)
1 parent 7867e7c commit c8c0be7

12 files changed

+231
-237
lines changed

tests/app/navigation/custom-transition.android.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ export class CustomTransition extends transition.Transition {
55
super(duration, curve);
66
}
77

8-
public createAndroidAnimation(transitionType: string): android.view.animation.Animation {
9-
const scaleValues = [];
10-
8+
public createAndroidAnimator(transitionType: string): android.animation.Animator {
9+
var scaleValues = Array.create("float", 2);
1110
switch (transitionType) {
1211
case transition.AndroidTransitionType.enter:
1312
case transition.AndroidTransitionType.popEnter:
@@ -20,22 +19,18 @@ export class CustomTransition extends transition.Transition {
2019
scaleValues[1] = 0;
2120
break;
2221
}
23-
24-
const animationSet = new android.view.animation.AnimationSet(false);
25-
const duration = this.getDuration();
22+
var objectAnimators = Array.create(android.animation.Animator, 2);
23+
objectAnimators[0] = android.animation.ObjectAnimator.ofFloat(null, "scaleX", scaleValues);
24+
objectAnimators[1] = android.animation.ObjectAnimator.ofFloat(null, "scaleY", scaleValues);
25+
var animatorSet = new android.animation.AnimatorSet();
26+
animatorSet.playTogether(objectAnimators);
27+
28+
var duration = this.getDuration();
2629
if (duration !== undefined) {
27-
animationSet.setDuration(duration);
30+
animatorSet.setDuration(duration);
2831
}
32+
animatorSet.setInterpolator(this.getCurve());
2933

30-
animationSet.setInterpolator(this.getCurve());
31-
animationSet.addAnimation(
32-
new android.view.animation.ScaleAnimation(
33-
scaleValues[0],
34-
scaleValues[1],
35-
scaleValues[0],
36-
scaleValues[1]
37-
));
38-
39-
return animationSet;
34+
return animatorSet;
4035
}
4136
}

tns-core-modules/ui/frame/fragment.android.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ class FragmentClass extends android.support.v4.app.Fragment {
1414
this._callbacks.onHiddenChanged(this, hidden, super.onHiddenChanged);
1515
}
1616

17-
public onCreateAnimation(transit: number, enter: boolean, nextAnim: number): android.view.animation.Animation {
18-
return this._callbacks.onCreateAnimation(this, transit, enter, nextAnim, super.onCreateAnimation);
17+
public onCreateAnimator(transit: number, enter: boolean, nextAnim: number): android.animation.Animator {
18+
let result = this._callbacks.onCreateAnimator(this, transit, enter, nextAnim, super.onCreateAnimator);
19+
return result;
1920
}
2021

2122
public onStop(): void {

tns-core-modules/ui/frame/fragment.transitions.android.ts

Lines changed: 94 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -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

5151
const sdkVersion = lazy(() => parseInt(device.sdkVersion));
52+
const intEvaluator = lazy(() => new android.animation.IntEvaluator());
5253
const defaultInterpolator = lazy(() => new android.view.animation.AccelerateDecelerateInterpolator());
5354

5455
export const waitingQueue = new Map<number, Set<ExpandedEntry>>();
5556
export const completedEntries = new Map<number, ExpandedEntry>();
5657

5758
let TransitionListener: TransitionListener;
58-
let AnimationListener: android.view.animation.Animation.AnimationListener;
59+
let AnimationListener: android.animation.Animator.AnimatorListener;
5960

6061
export 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

208209
export 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

384386
function 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,
617620
function 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

637640
function 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

656659
function 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

672675
function 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+
748763
class 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
}

tns-core-modules/ui/frame/fragment.transitions.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function _setAndroidFragmentTransitions(
2828
/**
2929
* @private
3030
*/
31-
export function _onFragmentCreateAnimation(entry: BackstackEntry, fragment: any, nextAnim: number, enter: boolean): any;
31+
export function _onFragmentCreateAnimator(entry: BackstackEntry, fragment: any, nextAnim: number, enter: boolean): any;
3232
/**
3333
* @private
3434
*/

0 commit comments

Comments
 (0)