refactor: restore animators api usage (#6403)

This commit is contained in:
Manol Donev
2018-10-16 15:37:57 +03:00
committed by GitHub
parent 7867e7ce5b
commit c8c0be7684
12 changed files with 229 additions and 235 deletions

View File

@ -5,9 +5,8 @@ export class CustomTransition extends transition.Transition {
super(duration, curve);
}
public createAndroidAnimation(transitionType: string): android.view.animation.Animation {
const scaleValues = [];
public createAndroidAnimator(transitionType: string): android.animation.Animator {
var scaleValues = Array.create("float", 2);
switch (transitionType) {
case transition.AndroidTransitionType.enter:
case transition.AndroidTransitionType.popEnter:
@ -20,22 +19,18 @@ export class CustomTransition extends transition.Transition {
scaleValues[1] = 0;
break;
}
const animationSet = new android.view.animation.AnimationSet(false);
const duration = this.getDuration();
var objectAnimators = Array.create(android.animation.Animator, 2);
objectAnimators[0] = android.animation.ObjectAnimator.ofFloat(null, "scaleX", scaleValues);
objectAnimators[1] = android.animation.ObjectAnimator.ofFloat(null, "scaleY", scaleValues);
var animatorSet = new android.animation.AnimatorSet();
animatorSet.playTogether(objectAnimators);
var duration = this.getDuration();
if (duration !== undefined) {
animationSet.setDuration(duration);
animatorSet.setDuration(duration);
}
animatorSet.setInterpolator(this.getCurve());
animationSet.setInterpolator(this.getCurve());
animationSet.addAnimation(
new android.view.animation.ScaleAnimation(
scaleValues[0],
scaleValues[1],
scaleValues[0],
scaleValues[1]
));
return animationSet;
return animatorSet;
}
}

View File

@ -14,8 +14,9 @@ class FragmentClass extends android.support.v4.app.Fragment {
this._callbacks.onHiddenChanged(this, hidden, super.onHiddenChanged);
}
public onCreateAnimation(transit: number, enter: boolean, nextAnim: number): android.view.animation.Animation {
return this._callbacks.onCreateAnimation(this, transit, enter, nextAnim, super.onCreateAnimation);
public onCreateAnimator(transit: number, enter: boolean, nextAnim: number): android.animation.Animator {
let result = this._callbacks.onCreateAnimator(this, transit, enter, nextAnim, super.onCreateAnimator);
return result;
}
public onStop(): void {

View File

@ -19,7 +19,7 @@ interface TransitionListener {
new(entry: ExpandedEntry, transition: android.transition.Transition): ExpandedTransitionListener;
}
interface ExpandedAnimation extends android.view.animation.Animation {
interface ExpandedAnimator extends android.animation.Animator {
entry: ExpandedEntry;
transitionType?: string;
}
@ -35,13 +35,13 @@ interface ExpandedEntry extends BackstackEntry {
reenterTransitionListener: ExpandedTransitionListener;
returnTransitionListener: ExpandedTransitionListener;
enterAnimation: ExpandedAnimation;
exitAnimation: ExpandedAnimation;
popEnterAnimation: ExpandedAnimation;
popExitAnimation: ExpandedAnimation;
enterAnimator: ExpandedAnimator;
exitAnimator: ExpandedAnimator;
popEnterAnimator: ExpandedAnimator;
popExitAnimator: ExpandedAnimator;
defaultEnterAnimation: ExpandedAnimation;
defaultExitAnimation: ExpandedAnimation;
defaultEnterAnimator: ExpandedAnimator;
defaultExitAnimator: ExpandedAnimator;
transition: Transition;
transitionName: string;
@ -49,13 +49,14 @@ interface ExpandedEntry extends BackstackEntry {
}
const sdkVersion = lazy(() => parseInt(device.sdkVersion));
const intEvaluator = lazy(() => new android.animation.IntEvaluator());
const defaultInterpolator = lazy(() => new android.view.animation.AccelerateDecelerateInterpolator());
export const waitingQueue = new Map<number, Set<ExpandedEntry>>();
export const completedEntries = new Map<number, ExpandedEntry>();
let TransitionListener: TransitionListener;
let AnimationListener: android.view.animation.Animation.AnimationListener;
let AnimationListener: android.animation.Animator.AnimatorListener;
export function _setAndroidFragmentTransitions(
animated: boolean,
@ -170,39 +171,39 @@ export function _setAndroidFragmentTransitions(
printTransitions(newEntry);
}
export function _onFragmentCreateAnimation(entry: ExpandedEntry, fragment: android.support.v4.app.Fragment, nextAnim: number, enter: boolean): android.view.animation.Animation {
let animation: android.view.animation.Animation;
export function _onFragmentCreateAnimator(entry: ExpandedEntry, fragment: android.support.v4.app.Fragment, nextAnim: number, enter: boolean): android.animation.Animator {
let animator: android.animation.Animator;
switch (nextAnim) {
case AnimationType.enterFakeResourceId:
animation = entry.enterAnimation;
animator = entry.enterAnimator;
break;
case AnimationType.exitFakeResourceId:
animation = entry.exitAnimation;
animator = entry.exitAnimator;
break;
case AnimationType.popEnterFakeResourceId:
animation = entry.popEnterAnimation;
animator = entry.popEnterAnimator;
break;
case AnimationType.popExitFakeResourceId:
animation = entry.popExitAnimation;
animator = entry.popExitAnimator;
break;
}
if (!animation && sdkVersion() >= 21) {
if (!animator && sdkVersion() >= 21) {
const view = fragment.getView();
const jsParent = entry.resolvedPage.parent;
const parent = view.getParent() || (jsParent && jsParent.nativeViewProtected);
const animatedEntries = _getAnimatedEntries(entry.frameId);
if (!animatedEntries || !animatedEntries.has(entry)) {
if (parent && !(<any>parent).isLaidOut()) {
animation = enter ? entry.defaultEnterAnimation : entry.defaultExitAnimation;
animator = enter ? entry.defaultEnterAnimator : entry.defaultExitAnimator;
}
}
}
return animation;
return animator;
}
export function _getAnimatedEntries(frameId: number): Set<BackstackEntry> {
@ -312,40 +313,40 @@ function getTransitionListener(entry: ExpandedEntry, transition: android.transit
return new TransitionListener(entry, transition);
}
function getAnimationListener(): android.view.animation.Animation.AnimationListener {
function getAnimationListener(): android.animation.Animator.AnimatorListener {
if (!AnimationListener) {
@Interfaces([android.view.animation.Animation.AnimationListener])
class AnimationListenerImpl extends java.lang.Object implements android.view.animation.Animation.AnimationListener {
@Interfaces([android.animation.Animator.AnimatorListener])
class AnimationListenerImpl extends java.lang.Object implements android.animation.Animator.AnimatorListener {
constructor() {
super();
return global.__native(this);
}
onAnimationStart(animation: ExpandedAnimation): void {
const entry = animation.entry;
onAnimationStart(animator: ExpandedAnimator): void {
const entry = animator.entry;
addToWaitingQueue(entry);
if (traceEnabled()) {
traceWrite(`START ${animation.transitionType} for ${entry.fragmentTag}`, traceCategories.Transition);
traceWrite(`START ${animator.transitionType} for ${entry.fragmentTag}`, traceCategories.Transition);
}
}
onAnimationRepeat(animation: ExpandedAnimation): void {
onAnimationRepeat(animator: ExpandedAnimator): void {
if (traceEnabled()) {
traceWrite(`REPEAT ${animation.transitionType} for ${animation.entry.fragmentTag}`, traceCategories.Transition);
traceWrite(`REPEAT ${animator.transitionType} for ${animator.entry.fragmentTag}`, traceCategories.Transition);
}
}
onAnimationEnd(animation: ExpandedAnimation): void {
onAnimationEnd(animator: ExpandedAnimator): void {
if (traceEnabled()) {
traceWrite(`END ${animation.transitionType} for ${animation.entry.fragmentTag}`, traceCategories.Transition);
traceWrite(`END ${animator.transitionType} for ${animator.entry.fragmentTag}`, traceCategories.Transition);
}
transitionOrAnimationCompleted(animation.entry);
transitionOrAnimationCompleted(animator.entry);
}
onAnimationCancel(animation: ExpandedAnimation): void {
onAnimationCancel(animator: ExpandedAnimator): void {
if (traceEnabled()) {
traceWrite(`CANCEL ${animation.transitionType} for ${animation.entry.fragmentTag}`, traceCategories.Transition);
traceWrite(`CANCEL ${animator.transitionType} for ${animator.entry.fragmentTag}`, traceCategories.Transition);
}
}
}
@ -367,18 +368,19 @@ function addToWaitingQueue(entry: ExpandedEntry): void {
entries.add(entry);
}
function clearAnimationListener(animation: ExpandedAnimation): void {
if (!animation) {
function clearAnimationListener(animator: ExpandedAnimator, listener: android.animation.Animator.AnimatorListener): void {
if (!animator) {
return;
}
animator.removeListener(listener);
if (traceEnabled()) {
const entry = animation.entry;
traceWrite(`Clear ${animation.transitionType} - ${entry.transition} for ${entry.fragmentTag}`, traceCategories.Transition);
const entry = animator.entry;
traceWrite(`Clear ${animator.transitionType} - ${entry.transition} for ${entry.fragmentTag}`, traceCategories.Transition);
}
animation.setAnimationListener(null);
animation.entry = null;
animator.entry = null;
}
function clearExitAndReenterTransitions(entry: ExpandedEntry, removeListener: boolean): void {
@ -477,10 +479,11 @@ function clearEntry(entry: ExpandedEntry, removeListener: boolean): void {
}
if (removeListener) {
clearAnimationListener(entry.enterAnimation);
clearAnimationListener(entry.exitAnimation);
clearAnimationListener(entry.popEnterAnimation);
clearAnimationListener(entry.popExitAnimation);
const listener = getAnimationListener();
clearAnimationListener(entry.enterAnimator, listener);
clearAnimationListener(entry.exitAnimator, listener);
clearAnimationListener(entry.popEnterAnimator, listener);
clearAnimationListener(entry.popExitAnimator, listener);
}
}
@ -617,21 +620,21 @@ function setupNewFragmentExplodeTransition(navTransition: NavigationTransition,
function setupExitAndPopEnterAnimation(entry: ExpandedEntry, transition: Transition): void {
const listener = getAnimationListener();
// remove previous listener if we are changing the animation.
clearAnimationListener(entry.exitAnimation);
clearAnimationListener(entry.popEnterAnimation);
// remove previous listener if we are changing the animator.
clearAnimationListener(entry.exitAnimator, listener);
clearAnimationListener(entry.popEnterAnimator, listener);
const exitAnimation = <ExpandedAnimation>transition.createAndroidAnimation(AndroidTransitionType.exit);
exitAnimation.transitionType = AndroidTransitionType.exit;
exitAnimation.entry = entry;
exitAnimation.setAnimationListener(listener);
entry.exitAnimation = exitAnimation;
const exitAnimator = <ExpandedAnimator>transition.createAndroidAnimator(AndroidTransitionType.exit);
exitAnimator.transitionType = AndroidTransitionType.exit;
exitAnimator.entry = entry;
exitAnimator.addListener(listener);
entry.exitAnimator = exitAnimator;
const popEnterAnimation = <ExpandedAnimation>transition.createAndroidAnimation(AndroidTransitionType.popEnter);
popEnterAnimation.transitionType = AndroidTransitionType.popEnter;
popEnterAnimation.entry = entry;
popEnterAnimation.setAnimationListener(listener);
entry.popEnterAnimation = popEnterAnimation;
const popEnterAnimator = <ExpandedAnimator>transition.createAndroidAnimator(AndroidTransitionType.popEnter);
popEnterAnimator.transitionType = AndroidTransitionType.popEnter;
popEnterAnimator.entry = entry;
popEnterAnimator.addListener(listener);
entry.popEnterAnimator = popEnterAnimator;
}
function setupAllAnimation(entry: ExpandedEntry, transition: Transition): void {
@ -640,33 +643,33 @@ function setupAllAnimation(entry: ExpandedEntry, transition: Transition): void {
// setupAllAnimation is called only for new fragments so we don't
// need to clearAnimationListener for enter & popExit animators.
const enterAnimation = <ExpandedAnimation>transition.createAndroidAnimation(AndroidTransitionType.enter);
enterAnimation.transitionType = AndroidTransitionType.enter;
enterAnimation.entry = entry;
enterAnimation.setAnimationListener(listener);
entry.enterAnimation = enterAnimation;
const enterAnimator = <ExpandedAnimator>transition.createAndroidAnimator(AndroidTransitionType.enter);
enterAnimator.transitionType = AndroidTransitionType.enter;
enterAnimator.entry = entry;
enterAnimator.addListener(listener);
entry.enterAnimator = enterAnimator;
const popExitAnimation = <ExpandedAnimation>transition.createAndroidAnimation(AndroidTransitionType.popExit);
popExitAnimation.transitionType = AndroidTransitionType.popExit;
popExitAnimation.entry = entry;
popExitAnimation.setAnimationListener(listener);
entry.popExitAnimation = popExitAnimation;
const popExitAnimator = <ExpandedAnimator>transition.createAndroidAnimator(AndroidTransitionType.popExit);
popExitAnimator.transitionType = AndroidTransitionType.popExit;
popExitAnimator.entry = entry;
popExitAnimator.addListener(listener);
entry.popExitAnimator = popExitAnimator;
}
function setupDefaultAnimations(entry: ExpandedEntry, transition: Transition): void {
const listener = getAnimationListener();
const enterAnimation = <ExpandedAnimation>transition.createAndroidAnimation(AndroidTransitionType.enter);
enterAnimation.transitionType = AndroidTransitionType.enter;
enterAnimation.entry = entry;
enterAnimation.setAnimationListener(listener);
entry.defaultEnterAnimation = enterAnimation;
const enterAnimator = <ExpandedAnimator>transition.createAndroidAnimator(AndroidTransitionType.enter);
enterAnimator.transitionType = AndroidTransitionType.enter;
enterAnimator.entry = entry;
enterAnimator.addListener(listener);
entry.defaultEnterAnimator = enterAnimator;
const exitAnimation = <ExpandedAnimation>transition.createAndroidAnimation(AndroidTransitionType.exit);
exitAnimation.transitionType = AndroidTransitionType.exit;
exitAnimation.entry = entry;
exitAnimation.setAnimationListener(listener);
entry.defaultExitAnimation = exitAnimation;
const exitAnimator = <ExpandedAnimator>transition.createAndroidAnimator(AndroidTransitionType.exit);
exitAnimator.transitionType = AndroidTransitionType.exit;
exitAnimator.entry = entry;
exitAnimator.addListener(listener);
entry.defaultExitAnimator = exitAnimator;
}
function setUpNativeTransition(navigationTransition: NavigationTransition, nativeTransition: android.transition.Transition) {
@ -729,10 +732,10 @@ function printTransitions(entry: ExpandedEntry) {
}
if (entry.transition) {
result += `enterAnimator=${entry.enterAnimation}, `;
result += `exitAnimator=${entry.exitAnimation}, `;
result += `popEnterAnimator=${entry.popEnterAnimation}, `;
result += `popExitAnimator=${entry.popExitAnimation}, `;
result += `enterAnimator=${entry.enterAnimator}, `;
result += `exitAnimator=${entry.exitAnimator}, `;
result += `popEnterAnimator=${entry.popEnterAnimator}, `;
result += `popExitAnimator=${entry.popExitAnimator}, `;
}
if (sdkVersion() >= 21) {
const fragment = entry.fragment;
@ -745,16 +748,20 @@ function printTransitions(entry: ExpandedEntry) {
}
}
class NoTransition extends Transition {
public createAndroidAnimation(transitionType: string): android.view.animation.Animation {
const animation = new android.view.animation.AlphaAnimation(1, 1);
// NOTE: this should not be necessary when we revert to Animators API
// HACK: Android view animation with zero duration seems to be buggy and raises animation listener events in illogical (wrong?) order:
// "enter" start -> "enter" end -> "exit" start -> "exit" end;
// we would expect events to overlap "exit" start -> "enter" start -> "exit" end -> "enter" end, or at least
// "exit" start / end to be raised before "enter" start / end
animation.setDuration(1);
function javaObjectArray(...params: java.lang.Object[]) {
const nativeArray = Array.create(java.lang.Object, params.length);
params.forEach((value, i) => nativeArray[i] = value);
return nativeArray;
}
return animation;
function createDummyZeroDurationAnimator(): android.animation.Animator {
const animator = android.animation.ValueAnimator.ofObject(intEvaluator(), javaObjectArray(java.lang.Integer.valueOf(0), java.lang.Integer.valueOf(1)));
animator.setDuration(0);
return animator;
}
class NoTransition extends Transition {
public createAndroidAnimator(transitionType: string): android.animation.Animator {
return createDummyZeroDurationAnimator();
}
}

View File

@ -28,7 +28,7 @@ export function _setAndroidFragmentTransitions(
/**
* @private
*/
export function _onFragmentCreateAnimation(entry: BackstackEntry, fragment: any, nextAnim: number, enter: boolean): any;
export function _onFragmentCreateAnimator(entry: BackstackEntry, fragment: any, nextAnim: number, enter: boolean): any;
/**
* @private
*/

View File

@ -13,7 +13,7 @@ import {
} from "./frame-common";
import {
_setAndroidFragmentTransitions, _onFragmentCreateAnimation, _getAnimatedEntries,
_setAndroidFragmentTransitions, _onFragmentCreateAnimator, _getAnimatedEntries,
_updateTransitions, _reverseTransitions, _clearEntry, _clearFragment, AnimationType
} from "./fragment.transitions";
@ -667,7 +667,7 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
}
@profile
public onCreateAnimation(fragment: android.support.v4.app.Fragment, transit: number, enter: boolean, nextAnim: number, superFunc: Function): android.view.animation.Animation {
public onCreateAnimator(fragment: android.support.v4.app.Fragment, transit: number, enter: boolean, nextAnim: number, superFunc: Function): android.animation.Animator {
let nextAnimString: string;
switch (nextAnim) {
case AnimationType.enterFakeResourceId: nextAnimString = "enter"; break;
@ -676,16 +676,16 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
case AnimationType.popExitFakeResourceId: nextAnimString = "popExit"; break;
}
let animation = _onFragmentCreateAnimation(this.entry, fragment, nextAnim, enter);
if (!animation) {
animation = superFunc.call(fragment, transit, enter, nextAnim);
let animator = _onFragmentCreateAnimator(this.entry, fragment, nextAnim, enter);
if (!animator) {
animator = superFunc.call(fragment, transit, enter, nextAnim);
}
if (traceEnabled()) {
traceWrite(`${fragment}.onCreateAnimation(${transit}, ${enter ? "enter" : "exit"}, ${nextAnimString}): ${animation ? "animation" : "no animation"}`, traceCategories.NativeLifecycle);
traceWrite(`${fragment}.onCreateAnimator(${transit}, ${enter ? "enter" : "exit"}, ${nextAnimString}): ${animator ? "animator" : "no animator"}`, traceCategories.NativeLifecycle);
}
return animation;
return animator;
}
@profile

View File

@ -414,7 +414,7 @@ export interface AndroidActivityCallbacks {
export interface AndroidFragmentCallbacks {
onHiddenChanged(fragment: any, hidden: boolean, superFunc: Function): void;
onCreateAnimation(fragment: any, transit: number, enter: boolean, nextAnim: number, superFunc: Function): any;
onCreateAnimator(fragment: any, transit: number, enter: boolean, nextAnim: number, superFunc: Function): any;
onCreate(fragment: any, savedInstanceState: any, superFunc: Function): void;
onCreateView(fragment: any, inflater: any, container: any, savedInstanceState: any, superFunc: Function): any;
onSaveInstanceState(fragment: any, outState: any, superFunc: Function): void;

View File

@ -1,29 +1,28 @@
import { Transition, AndroidTransitionType } from "./transition";
export class FadeTransition extends Transition {
public createAndroidAnimation(transitionType: string): android.view.animation.Animation {
const alphaValues = [];
public createAndroidAnimator(transitionType: string): android.animation.Animator {
const alphaValues = Array.create("float", 2);
switch (transitionType) {
case AndroidTransitionType.enter:
case AndroidTransitionType.popEnter:
alphaValues[0] = 0.0;
alphaValues[1] = 1.0;
alphaValues[0] = 0;
alphaValues[1] = 1;
break;
case AndroidTransitionType.exit:
case AndroidTransitionType.popExit:
alphaValues[0] = 1.0;
alphaValues[1] = 0.0;
alphaValues[0] = 1;
alphaValues[1] = 0;
break;
}
const animation = new android.view.animation.AlphaAnimation(alphaValues[0], alphaValues[1]);
const animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", alphaValues);
const duration = this.getDuration();
if (duration !== undefined) {
animation.setDuration(duration);
animator.setDuration(duration);
}
animation.setInterpolator(this.getCurve());
return animation;
animator.setInterpolator(this.getCurve());
return animator;
}
}

View File

@ -1,6 +1,6 @@
import { Transition, AndroidTransitionType } from "./transition";
// http://developer.android.com/training/animation/cardflip.html
//http://developer.android.com/training/animation/cardflip.html
export class FlipTransition extends Transition {
private _direction: string;
@ -9,117 +9,109 @@ export class FlipTransition extends Transition {
this._direction = direction;
}
public createAndroidAnimation(transitionType: string): android.view.animation.Animation {
ensureRotate3dAnimationClass();
let animation: android.view.animation.Animation;
let animationSet: android.view.animation.AnimationSet
let rotateAnimation: android.view.animation.Animation;
let alphaAnimation: android.view.animation.Animation;
public createAndroidAnimator(transitionType: string): android.animation.Animator {
let objectAnimators;
let values;
let animator: android.animation.ObjectAnimator;
const animatorSet = new android.animation.AnimatorSet();
const fullDuration = this.getDuration() || 300;
const interpolator = this.getCurve();
const rotationY = this._direction === "right" ? 180 : -180;
switch (transitionType) {
case AndroidTransitionType.enter: // card_flip_right_in
animation = new Rotate3dAnimationClass(rotationY, 0.0, 0.5, 0.5);
animation.setInterpolator(interpolator);
animation.setDuration(fullDuration);
objectAnimators = Array.create(android.animation.Animator, 3);
values = Array.create("float", 2);
values[0] = 1.0;
values[1] = 0.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", values);
animator.setDuration(0);
objectAnimators[0] = animator;
values = Array.create("float", 2);
values[0] = rotationY;
values[1] = 0.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "rotationY", values);
animator.setInterpolator(interpolator);
animator.setDuration(fullDuration);
objectAnimators[1] = animator;
values = Array.create("float", 2);
values[0] = 0.0;
values[1] = 1.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", values);
animator.setStartDelay(fullDuration / 2);
animator.setDuration(1);
objectAnimators[2] = animator;
break;
case AndroidTransitionType.exit: // card_flip_right_out
animation = animationSet = new android.view.animation.AnimationSet(false /* shareInterpolator */);
rotateAnimation = new Rotate3dAnimationClass(0.0, -rotationY, 0.5, 0.5);
rotateAnimation.setInterpolator(interpolator);
rotateAnimation.setDuration(fullDuration);
animationSet.addAnimation(rotateAnimation);
objectAnimators = Array.create(android.animation.Animator, 2);
alphaAnimation = new android.view.animation.AlphaAnimation(1.0, 0.0);
alphaAnimation.setStartOffset(fullDuration / 2);
alphaAnimation.setDuration(1);
animationSet.addAnimation(alphaAnimation);
values = Array.create("float", 2);
values[0] = 0.0;
values[1] = -rotationY;
animator = android.animation.ObjectAnimator.ofFloat(null, "rotationY", values);
animator.setInterpolator(interpolator);
animator.setDuration(fullDuration);
objectAnimators[0] = animator;
values = Array.create("float", 2);
values[0] = 1.0;
values[1] = 0.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", values);
animator.setStartDelay(fullDuration / 2);
animator.setDuration(1);
objectAnimators[1] = animator;
break;
case AndroidTransitionType.popEnter: // card_flip_left_in
animation = new Rotate3dAnimationClass(-rotationY, 0.0, 0.5, 0.5);
animation.setInterpolator(interpolator);
animation.setDuration(fullDuration);
objectAnimators = Array.create(android.animation.Animator, 3);
values = Array.create("float", 2);
values[0] = 1.0;
values[1] = 0.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", values);
animator.setDuration(0);
objectAnimators[0] = animator;
values = Array.create("float", 2);
values[0] = -rotationY;
values[1] = 0.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "rotationY", values);
animator.setInterpolator(interpolator);
animator.setDuration(fullDuration);
objectAnimators[1] = animator;
values = Array.create("float", 2);
values[0] = 0.0;
values[1] = 1.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", values);
animator.setStartDelay(fullDuration / 2);
animator.setDuration(1);
objectAnimators[2] = animator;
break;
case AndroidTransitionType.popExit: // card_flip_left_out
animation = animationSet = new android.view.animation.AnimationSet(false /* shareInterpolator */);
rotateAnimation = new Rotate3dAnimationClass(0.0, rotationY, 0.5, 0.5);
rotateAnimation.setInterpolator(interpolator);
rotateAnimation.setDuration(fullDuration);
animationSet.addAnimation(rotateAnimation);
objectAnimators = Array.create(android.animation.Animator, 2);
alphaAnimation = new android.view.animation.AlphaAnimation(1.0, 0.0);
alphaAnimation.setStartOffset(fullDuration / 2);
alphaAnimation.setDuration(1);
animationSet.addAnimation(alphaAnimation);
values = Array.create("float", 2);
values[0] = 0.0;
values[1] = rotationY;
animator = android.animation.ObjectAnimator.ofFloat(null, "rotationY", values);
animator.setInterpolator(interpolator);
animator.setDuration(fullDuration);
objectAnimators[0] = animator;
values = Array.create("float", 2);
values[0] = 1.0;
values[1] = 0.0;
animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", values);
animator.setStartDelay(fullDuration / 2);
animator.setDuration(1);
objectAnimators[1] = animator;
break;
}
return animation;
animatorSet.playTogether(objectAnimators);
return animatorSet;
}
}
let Rotate3dAnimationClass;
function ensureRotate3dAnimationClass() {
if (Rotate3dAnimationClass) {
return;
}
/**
* Creates a new 3D rotation on the Y axis. The rotation is defined by its
* start angle and its end angle. Both angles are in degrees. The rotation
* is performed around a center point on the 2D space, definied by a pair
* of X and Y coordinates, called centerX and centerY.
*
* @param fromDegrees the start angle of the 3D rotation
* @param toDegrees the end angle of the 3D rotation
* @param centerX the X center of the 3D rotation (relative to self)
* @param centerY the Y center of the 3D rotation (relative to self)
*/
class Rotate3dAnimation extends android.view.animation.Animation {
private _camera: android.graphics.Camera;
private _pivotX: number;
private _pivotY: number;
constructor(
private _fromDegrees: number,
private _toDegrees: number,
private _centerX: number,
private _centerY: number) {
super();
return global.__native(this);
}
public initialize(width: number, height: number, parentWidth: number, parentHeight: number) {
super.initialize(width, height, parentWidth, parentHeight);
this._pivotX = this.resolveSize(android.view.animation.Animation.RELATIVE_TO_SELF, this._centerX, width, parentWidth);
this._pivotY = this.resolveSize(android.view.animation.Animation.RELATIVE_TO_SELF, this._centerY, height, parentHeight);
this._camera = new android.graphics.Camera();
}
public applyTransformation(interpolatedTime: number, t: android.view.animation.Transformation) {
const fromDegrees = this._fromDegrees;
const degrees = fromDegrees + ((this._toDegrees - fromDegrees) * interpolatedTime);
const pivotX = this._pivotX;
const pivotY = this._pivotY;
const camera = this._camera;
const matrix: android.graphics.Matrix = t.getMatrix();
camera.save();
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-pivotX, -pivotY);
matrix.postTranslate(pivotX, pivotY);
}
}
Rotate3dAnimationClass = Rotate3dAnimation;
}

View File

@ -13,8 +13,8 @@ export class SlideTransition extends transition.Transition {
this._direction = direction;
}
public createAndroidAnimation(transitionType: string): android.view.animation.Animation {
const translationValues = [];
public createAndroidAnimator(transitionType: string): android.animation.Animator {
const translationValues = Array.create("float", 2);
switch (this._direction) {
case "left":
switch (transitionType) {
@ -98,22 +98,22 @@ export class SlideTransition extends transition.Transition {
break;
}
let animation;
let prop;
if (this._direction === "left" || this._direction === "right") {
animation = new android.view.animation.TranslateAnimation(translationValues[0], translationValues[1], 0, 0);
prop = "translationX";
}
else {
animation = new android.view.animation.TranslateAnimation(0, 0, translationValues[0], translationValues[1]);
prop = "translationY";
}
const animator = android.animation.ObjectAnimator.ofFloat(null, prop, translationValues);
const duration = this.getDuration();
if (duration !== undefined) {
animation.setDuration(duration);
animator.setDuration(duration);
}
animation.setInterpolator(this.getCurve());
return animation;
animator.setInterpolator(this.getCurve());
return animator;
}
public toString(): string {

View File

@ -38,7 +38,7 @@ export class Transition implements TransitionDefinition {
throw new Error("Abstract method call");
}
public createAndroidAnimation(transitionType: string): android.view.animation.Animation {
public createAndroidAnimator(transitionType: string): android.animation.Animator {
throw new Error("Abstract method call");
}

View File

@ -14,6 +14,6 @@ export class Transition {
public getDuration(): number;
public getCurve(): any;
public animateIOSTransition(containerView: any, fromView: any, toView: any, operation: any, completion: (finished: boolean) => void): void;
public createAndroidAnimation(transitionType: string): any;
public createAndroidAnimator(transitionType: string): any;
public toString(): string;
}

View File

@ -24,7 +24,7 @@ export class Transition implements TransitionDefinition {
throw new Error("Abstract method call");
}
public createAndroidAnimation(transitionType: string): any {
public createAndroidAnimator(transitionType: string): any {
throw new Error("Abstract method call");
}