diff --git a/apps/toolbox/src/pages/transitions.ts b/apps/toolbox/src/pages/transitions.ts index 79c352769..3b3f5157e 100644 --- a/apps/toolbox/src/pages/transitions.ts +++ b/apps/toolbox/src/pages/transitions.ts @@ -1,4 +1,4 @@ -import { Observable, EventData, Page, ShowModalOptions, SharedTransition, ModalTransition, PageTransition, Screen } from '@nativescript/core'; +import { Observable, EventData, Page, ShowModalOptions, SharedTransition, ModalTransition, PageTransition } from '@nativescript/core'; let page: Page; export function navigatingTo(args: EventData) { diff --git a/apps/toolbox/src/pages/transitions.xml b/apps/toolbox/src/pages/transitions.xml index eca284641..28b7d8d93 100644 --- a/apps/toolbox/src/pages/transitions.xml +++ b/apps/toolbox/src/pages/transitions.xml @@ -7,20 +7,17 @@ - - - - diff --git a/packages/core/ui/transition/page-transition.android.ts b/packages/core/ui/transition/page-transition.android.ts index 81595b5ad..3e18cdf64 100644 --- a/packages/core/ui/transition/page-transition.android.ts +++ b/packages/core/ui/transition/page-transition.android.ts @@ -1,87 +1,73 @@ +import { ViewBase } from '../core/view-base'; import { BackstackEntry } from '../frame'; -import { SharedTransition } from './shared-transition'; -// import { SlideTransition } from './slide-transition'; import { FadeTransition } from './fade-transition'; +import { SharedTransition } from './shared-transition'; + +@NativeClass +class CustomInterpolator extends android.view.animation.AnticipateOvershootInterpolator { + getInterpolation(input: number) { + // HACK: we speed up the interpolation by 10% to fix the issue with the transition not being finished + // and the views shifting from their intended final position... + // this is really just a hack and should be fixed properly once we + // can figure out the root cause of the issue. + const res = super.getInterpolation(input) * 1.1; + + if (res > 1) { + return float(1); + } + + return float(res); + } +} + +function setTransitionName(view: ViewBase) { + if (!view.sharedTransitionTag) { + return; + } + try { + androidx.core.view.ViewCompat.setTransitionName(view.nativeView, view.sharedTransitionTag); + } catch (err) { + // ignore + } +} export class PageTransition extends FadeTransition { - //SlideTransition - - constructor() { - super(500); - // when extending slide: - // super('left', 500); + constructor(duration?: number, curve?: any) { + // disable custom curves until we can fix the issue with the animation not completing + if (curve) { + console.warn('PageTransition does not support custom curves at the moment. The passed in curve will be ignored.'); + } + super(duration); } - // when extending slide: - // createAndroidAnimator(transitionType: string) { - // // console.log('HELLO PageTransition', transitionType); - // if ( - // [ - // Transition.AndroidTransitionType.enter, - // Transition.AndroidTransitionType.popEnter, - // Transition.AndroidTransitionType.popExit, - // // When extending SlideTransition, disable exit - // // This causes back navigation shared elements position to be off - // // Transition.AndroidTransitionType.exit, - // ].includes(transitionType) - // ) { - // return super.createAndroidAnimator(transitionType); - // } - // } - androidFragmentTransactionCallback(fragmentTransaction: androidx.fragment.app.FragmentTransaction, currentEntry: BackstackEntry, newEntry: BackstackEntry) { const fromPage = currentEntry.resolvedPage; const toPage = newEntry.resolvedPage; - - const currentFragment: androidx.fragment.app.Fragment = currentEntry ? currentEntry.fragment : null; const newFragment: androidx.fragment.app.Fragment = newEntry.fragment; - const { sharedElements, presented, presenting } = SharedTransition.getSharedElements(fromPage, toPage); - // fragmentTransaction.addSharedElement(); + const { presented, presenting } = SharedTransition.getSharedElements(fromPage, toPage); - toPage.on('loaded', () => { - presented.forEach((v) => { - console.log({ - presentedSharedElements: true, - nativeView: !!v.nativeView, - sharedTransitionTag: v.sharedTransitionTag, - }); - androidx.core.view.ViewCompat.setTransitionName(v.nativeView, v.sharedTransitionTag); - }); - - // setTimeout(() => { + toPage.once('loaded', () => { + presented.forEach(setTransitionName); newFragment.startPostponedEnterTransition(); - // }, 2000) }); presenting.forEach((v) => { - console.log({ - presentingSharedElements: true, - nativeView: !!v.nativeView, - sharedTransitionTag: v.sharedTransitionTag, - }); - androidx.core.view.ViewCompat.setTransitionName(v.nativeView, v.sharedTransitionTag); - }); - presenting.forEach((v) => { + setTransitionName(v); fragmentTransaction.addSharedElement(v.nativeView, v.sharedTransitionTag); }); fragmentTransaction.setReorderingAllowed(true); const transitionSet = new androidx.transition.TransitionSet(); - transitionSet.setDuration(500); + transitionSet.setDuration(this.getDuration()); transitionSet.addTransition(new androidx.transition.ChangeBounds()); transitionSet.addTransition(new androidx.transition.ChangeTransform()); - // transitionSet.addTransition(new androidx.transition.ChangeClipBounds()); + transitionSet.setInterpolator(new CustomInterpolator()); // postpone enter until we call "loaded" on the new page newFragment.postponeEnterTransition(); - newFragment.setSharedElementEnterTransition(transitionSet); newFragment.setSharedElementReturnTransition(transitionSet); - - // newFragment.setSharedElementReturnTransition(new androidx.transition.ChangeBounds()); - // currentFragment.setSharedElementEnterTransition(new androidx.transition.ChangeBounds()); - // currentFragment.setSharedElementReturnTransition(new androidx.transition.ChangeBounds()); } }