mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(core): Shared Element Transitions (#10022)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Transition } from '@nativescript/core';
|
||||
import { PageTransition, Transition } from '@nativescript/core';
|
||||
|
||||
export class CustomTransition extends Transition {
|
||||
constructor(duration: number, curve: any) {
|
||||
@@ -34,3 +34,5 @@ export class CustomTransition extends Transition {
|
||||
return animatorSet;
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomSharedElementPageTransition extends PageTransition {}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Transition } from '@nativescript/core/ui/transition';
|
||||
import { Transition, PageTransition } from '@nativescript/core';
|
||||
|
||||
export class CustomTransition extends Transition {
|
||||
constructor();
|
||||
constructor(duration: number, curve: any);
|
||||
}
|
||||
|
||||
export class CustomSharedElementPageTransition extends PageTransition {}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import * as transition from '@nativescript/core/ui/transition';
|
||||
import { PageTransition, SharedTransition, SharedTransitionHelper, Transition } from '@nativescript/core';
|
||||
|
||||
export class CustomTransition extends transition.Transition {
|
||||
export class CustomTransition extends Transition {
|
||||
constructor(duration: number, curve: any) {
|
||||
super(duration, curve);
|
||||
}
|
||||
|
||||
public animateIOSTransition(containerView: UIView, fromView: UIView, toView: UIView, operation: UINavigationControllerOperation, completion: (finished: boolean) => void): void {
|
||||
animateIOSTransition(transitionContext: UIViewControllerContextTransitioning, fromViewCtrl: UIViewController, toViewCtrl: UIViewController, operation: UINavigationControllerOperation): void {
|
||||
const toView = toViewCtrl.view;
|
||||
const fromView = fromViewCtrl.view;
|
||||
toView.transform = CGAffineTransformMakeScale(0, 0);
|
||||
fromView.transform = CGAffineTransformIdentity;
|
||||
|
||||
switch (operation) {
|
||||
case UINavigationControllerOperation.Push:
|
||||
containerView.insertSubviewAboveSubview(toView, fromView);
|
||||
transitionContext.containerView.insertSubviewAboveSubview(toView, fromView);
|
||||
break;
|
||||
case UINavigationControllerOperation.Pop:
|
||||
containerView.insertSubviewBelowSubview(toView, fromView);
|
||||
transitionContext.containerView.insertSubviewBelowSubview(toView, fromView);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -27,7 +29,63 @@ export class CustomTransition extends transition.Transition {
|
||||
toView.transform = CGAffineTransformIdentity;
|
||||
fromView.transform = CGAffineTransformMakeScale(0, 0);
|
||||
},
|
||||
completion
|
||||
(finished) => {
|
||||
transitionContext.completeTransition(finished);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomSharedElementPageTransition extends PageTransition {
|
||||
transitionController: PageTransitionController;
|
||||
interactiveController: UIPercentDrivenInteractiveTransition;
|
||||
presented: UIViewController;
|
||||
presenting: UIViewController;
|
||||
navigationController: UINavigationController;
|
||||
operation: number;
|
||||
|
||||
iosNavigatedController(navigationController: UINavigationController, operation: number, fromVC: UIViewController, toVC: UIViewController): UIViewControllerAnimatedTransitioning {
|
||||
this.navigationController = navigationController;
|
||||
if (!this.transitionController) {
|
||||
this.presented = toVC;
|
||||
this.presenting = fromVC;
|
||||
}
|
||||
this.transitionController = PageTransitionController.initWithOwner(new WeakRef(this));
|
||||
// console.log('iosNavigatedController presenting:', this.presenting);
|
||||
|
||||
this.operation = operation;
|
||||
return this.transitionController;
|
||||
}
|
||||
}
|
||||
|
||||
@NativeClass()
|
||||
class PageTransitionController extends NSObject implements UIViewControllerAnimatedTransitioning {
|
||||
static ObjCProtocols = [UIViewControllerAnimatedTransitioning];
|
||||
owner: WeakRef<PageTransition>;
|
||||
|
||||
static initWithOwner(owner: WeakRef<PageTransition>) {
|
||||
const ctrl = <PageTransitionController>PageTransitionController.new();
|
||||
ctrl.owner = owner;
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
transitionDuration(transitionContext: UIViewControllerContextTransitioning): number {
|
||||
const owner = this.owner.deref();
|
||||
if (owner) {
|
||||
return owner.getDuration();
|
||||
}
|
||||
return 0.35;
|
||||
}
|
||||
|
||||
animateTransition(transitionContext: UIViewControllerContextTransitioning): void {
|
||||
const owner = this.owner.deref();
|
||||
if (owner) {
|
||||
// console.log('--- PageTransitionController animateTransition');
|
||||
const state = SharedTransition.getState(owner.id);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
SharedTransitionHelper.animate(state, transitionContext, 'page');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import * as helper from '../ui-helper';
|
||||
import * as platform from '@nativescript/core/platform';
|
||||
import { Trace, CoreTypes } from '@nativescript/core';
|
||||
import { Color } from '@nativescript/core/color';
|
||||
import { NavigationEntry, NavigationTransition } from '@nativescript/core/ui/frame';
|
||||
import { Page } from '@nativescript/core/ui/page';
|
||||
import { CustomTransition } from './custom-transition';
|
||||
import { Color, Device, CoreTypes, Trace, SharedTransition, NavigationEntry, NavigationTransition, Page, platformNames, GridLayout } from '@nativescript/core';
|
||||
import { CustomTransition, CustomSharedElementPageTransition } from './custom-transition';
|
||||
|
||||
function _testTransition(navigationTransition: NavigationTransition) {
|
||||
var testId = `Transition[${JSON.stringify(navigationTransition)}]`;
|
||||
@@ -36,10 +32,10 @@ export function test_Transitions() {
|
||||
});
|
||||
|
||||
var transitions;
|
||||
if (platform.Device.os === platform.platformNames.ios) {
|
||||
if (Device.os === platformNames.ios) {
|
||||
transitions = ['curl'];
|
||||
} else {
|
||||
const _sdkVersion = parseInt(platform.Device.sdkVersion);
|
||||
const _sdkVersion = parseInt(Device.sdkVersion);
|
||||
transitions = _sdkVersion >= 21 ? ['explode'] : [];
|
||||
}
|
||||
|
||||
@@ -55,3 +51,59 @@ export function test_Transitions() {
|
||||
|
||||
// helper.navigateWithEntry({ create: mainPageFactory, clearHistory: true, animated: false });
|
||||
}
|
||||
|
||||
export function test_SharedElementTransitions() {
|
||||
helper.navigate(() => {
|
||||
const page = new Page();
|
||||
page.id = 'SharedelementTransitionsTestPage_MAIN';
|
||||
page.style.backgroundColor = new Color(255, Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255));
|
||||
const grid = new GridLayout();
|
||||
|
||||
const sharedElement = new GridLayout();
|
||||
sharedElement.width = { unit: 'dip', value: 200 };
|
||||
sharedElement.height = { unit: 'dip', value: 200 };
|
||||
sharedElement.marginTop = 20;
|
||||
sharedElement.borderRadius = 20;
|
||||
sharedElement.verticalAlignment = 'top';
|
||||
sharedElement.iosOverflowSafeArea = false;
|
||||
sharedElement.backgroundColor = new Color('yellow');
|
||||
sharedElement.sharedTransitionTag = 'testing';
|
||||
grid.addChild(sharedElement);
|
||||
|
||||
page.content = grid;
|
||||
return page;
|
||||
});
|
||||
|
||||
const navigationTransition = SharedTransition.custom(new CustomSharedElementPageTransition());
|
||||
|
||||
var testId = `SharedElementTransition[${JSON.stringify(navigationTransition)}]`;
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`Testing ${testId}`, Trace.categories.Test);
|
||||
}
|
||||
var navigationEntry: NavigationEntry = {
|
||||
create: function (): Page {
|
||||
let page = new Page();
|
||||
page.id = testId;
|
||||
page.style.backgroundColor = new Color(255, Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255));
|
||||
const grid = new GridLayout();
|
||||
|
||||
const sharedElement = new GridLayout();
|
||||
sharedElement.width = { unit: 'dip', value: 60 };
|
||||
sharedElement.height = { unit: 'dip', value: 60 };
|
||||
sharedElement.marginTop = 20;
|
||||
sharedElement.borderRadius = 30;
|
||||
sharedElement.verticalAlignment = 'top';
|
||||
sharedElement.iosOverflowSafeArea = false;
|
||||
sharedElement.backgroundColor = new Color('purple');
|
||||
sharedElement.sharedTransitionTag = 'testing';
|
||||
grid.addChild(sharedElement);
|
||||
|
||||
page.content = grid;
|
||||
return page;
|
||||
},
|
||||
animated: true,
|
||||
transition: navigationTransition,
|
||||
};
|
||||
|
||||
helper.navigateWithEntry(navigationEntry);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user