mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
chore: cleanup
This commit is contained in:
@@ -15,7 +15,11 @@ export class TransitionsModel extends Observable {
|
||||
page.frame.navigate({
|
||||
moduleName: `pages/transitions/transitions-detail`,
|
||||
transition: SharedTransition.custom(new PageTransition(), {
|
||||
interactiveDismissal: true,
|
||||
interactive: {
|
||||
dismiss: {
|
||||
finishThreshold: 0.5,
|
||||
},
|
||||
},
|
||||
// toPageStart: {
|
||||
// duration: 400,
|
||||
// },
|
||||
@@ -29,7 +33,11 @@ export class TransitionsModel extends Observable {
|
||||
openModal() {
|
||||
page.showModal('pages/transitions/transitions-modal', {
|
||||
transition: SharedTransition.custom(new ModalTransition(), {
|
||||
interactiveDismissal: true,
|
||||
interactive: {
|
||||
dismiss: {
|
||||
finishThreshold: 0.5,
|
||||
},
|
||||
},
|
||||
toPageStart: {
|
||||
y: 200,
|
||||
// duration: 400,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUser
|
||||
import { ShowModalOptions, hiddenProperty } from '../view-base';
|
||||
import { Trace } from '../../../trace';
|
||||
import { layout, iOSNativeHelper } from '../../../utils';
|
||||
import { isNumber } from '../../../utils/types';
|
||||
import { IOSHelper } from './view-helper';
|
||||
import { ios as iosBackground, Background } from '../../styling/background';
|
||||
import { perspectiveProperty, visibilityProperty, opacityProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, clipPathProperty } from '../../styling/style-properties';
|
||||
@@ -32,7 +33,7 @@ const majorVersion = iOSNativeHelper.MajorVersion;
|
||||
export class View extends ViewCommon implements ViewDefinition {
|
||||
nativeViewProtected: UIView;
|
||||
viewController: UIViewController;
|
||||
transitionIteractiveCtrl: UIPercentDrivenInteractiveTransition;
|
||||
transitionInteractiveCtrl: UIPercentDrivenInteractiveTransition;
|
||||
private _popoverPresentationDelegate: IOSHelper.UIPopoverPresentationControllerDelegateImp;
|
||||
private _adaptivePresentationDelegate: IOSHelper.UIAdaptivePresentationControllerDelegateImp;
|
||||
private _transitioningDelegate: UIViewControllerTransitioningDelegateImpl;
|
||||
@@ -473,7 +474,7 @@ export class View extends ViewCommon implements ViewDefinition {
|
||||
this._transitioningDelegate = UIViewControllerTransitioningDelegateImpl.initWithOwner(new WeakRef(options.transition.instance), new WeakRef(this));
|
||||
controller.transitioningDelegate = this._transitioningDelegate;
|
||||
const transitionState = SharedTransition.getState(options.transition.instance.id);
|
||||
if (transitionState?.interactiveDismissal) {
|
||||
if (transitionState?.interactive?.dismiss) {
|
||||
// interactive transitions via gestures
|
||||
// TODO - these could be typed as: boolean | (view: View) => void
|
||||
// to allow users to define their own custom gesture dismissals
|
||||
@@ -563,11 +564,13 @@ export class View extends ViewCommon implements ViewDefinition {
|
||||
|
||||
private _interactiveDismissGestureHandler(args: PanGestureEventData) {
|
||||
if (args?.ios?.view) {
|
||||
this.interactiveDismissGestureBegan = true;
|
||||
this.interactiveDismissGestureCancelled = false;
|
||||
const percent = args.deltaY / (args.ios.view.bounds.size.height / 2);
|
||||
this._updateInteractiveTransition({
|
||||
began: true,
|
||||
cancelled: false,
|
||||
});
|
||||
const percent = this.interactiveTransition?.options.percentFormula ? this.interactiveTransition?.options.percentFormula(args) : args.deltaY / (args.ios.view.bounds.size.height / 2);
|
||||
if (SharedTransition.DEBUG) {
|
||||
console.log('interactive dismissal pan:', percent);
|
||||
console.log('Interactive dismissal percentage:', percent);
|
||||
}
|
||||
switch (args.state) {
|
||||
case GestureStateTypes.began:
|
||||
@@ -576,21 +579,23 @@ export class View extends ViewCommon implements ViewDefinition {
|
||||
}
|
||||
break;
|
||||
case GestureStateTypes.changed:
|
||||
// TODO: allow customization of threshold
|
||||
if (percent < 1) {
|
||||
if (this.transitionIteractiveCtrl) {
|
||||
this.transitionIteractiveCtrl.updateInteractiveTransition(percent);
|
||||
if (this.transitionInteractiveCtrl) {
|
||||
this.transitionInteractiveCtrl.updateInteractiveTransition(percent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GestureStateTypes.cancelled:
|
||||
case GestureStateTypes.ended:
|
||||
if (this.transitionIteractiveCtrl) {
|
||||
if (percent > 0.5) {
|
||||
this.transitionIteractiveCtrl.finishInteractiveTransition();
|
||||
if (this.transitionInteractiveCtrl) {
|
||||
const finishThreshold = isNumber(this.interactiveTransition?.options?.finishThreshold) ? this.interactiveTransition?.options?.finishThreshold : 0.5;
|
||||
if (percent > finishThreshold) {
|
||||
this.transitionInteractiveCtrl.finishInteractiveTransition();
|
||||
} else {
|
||||
this.interactiveDismissGestureCancelled = true;
|
||||
this.transitionIteractiveCtrl.cancelInteractiveTransition();
|
||||
this._updateInteractiveTransition({
|
||||
cancelled: true,
|
||||
});
|
||||
this.transitionInteractiveCtrl.cancelInteractiveTransition();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -619,9 +624,9 @@ export class View extends ViewCommon implements ViewDefinition {
|
||||
}
|
||||
|
||||
parentController.dismissViewControllerAnimatedCompletion(animated, () => {
|
||||
if (!this.interactiveDismissGestureCancelled) {
|
||||
if (!this.interactiveTransition?.cancelled) {
|
||||
this._transitioningDelegate = null;
|
||||
this.transitionIteractiveCtrl = null;
|
||||
this.transitionInteractiveCtrl = null;
|
||||
this.off('pan', this._interactiveDismissGesture);
|
||||
if (this._modalAnimatedOptions) {
|
||||
this._modalAnimatedOptions.pop();
|
||||
@@ -1013,9 +1018,9 @@ class UIViewControllerTransitioningDelegateImpl extends NSObject implements UIVi
|
||||
if (owner?.iosInteractionDismiss) {
|
||||
const ownerView = this.ownerView?.deref();
|
||||
if (ownerView) {
|
||||
if (ownerView.interactiveDismissGestureBegan) {
|
||||
ownerView.transitionIteractiveCtrl = owner.iosInteractionDismiss(animator);
|
||||
return ownerView.transitionIteractiveCtrl;
|
||||
if (ownerView.interactiveTransition?.began) {
|
||||
ownerView.transitionInteractiveCtrl = owner.iosInteractionDismiss(animator);
|
||||
return ownerView.transitionInteractiveCtrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import { AccessibilityEventOptions, AccessibilityLiveRegion, AccessibilityRole,
|
||||
import { accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
|
||||
import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, accessibilityPerformEscapeEvent, getCurrentFontScale } from '../../../accessibility';
|
||||
import { CSSShadow } from '../../styling/css-shadow';
|
||||
import { SharedTransition } from '../../transition/shared-transition';
|
||||
import { SharedTransition, SharedTransitionInteractiveOptions } from '../../transition/shared-transition';
|
||||
|
||||
// helpers (these are okay re-exported here)
|
||||
export * from './view-helper';
|
||||
@@ -69,6 +69,8 @@ export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator
|
||||
|
||||
export const _rootModalViews = new Array<ViewBase>();
|
||||
|
||||
type InteractiveTransitionState = { began?: boolean; cancelled?: boolean; options?: SharedTransitionInteractiveOptions };
|
||||
|
||||
export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
public static layoutChangedEvent = 'layoutChanged';
|
||||
public static shownModallyEvent = 'shownModally';
|
||||
@@ -94,8 +96,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
public _modalParent: ViewCommon;
|
||||
private _modalContext: any;
|
||||
private _modal: ViewCommon;
|
||||
interactiveDismissGestureBegan = false;
|
||||
interactiveDismissGestureCancelled = false;
|
||||
interactiveTransition: InteractiveTransitionState;
|
||||
|
||||
private _measuredWidth: number;
|
||||
private _measuredHeight: number;
|
||||
@@ -249,6 +250,13 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
return false;
|
||||
}
|
||||
|
||||
_updateInteractiveTransition(state: InteractiveTransitionState) {
|
||||
this.interactiveTransition = {
|
||||
...(this.interactiveTransition || {}),
|
||||
...state,
|
||||
};
|
||||
}
|
||||
|
||||
_setupAsRootView(context: any): void {
|
||||
super._setupAsRootView(context);
|
||||
if (!this._styleScope) {
|
||||
@@ -415,14 +423,16 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
};
|
||||
|
||||
const whenClosedCallback = () => {
|
||||
if (this.interactiveDismissGestureBegan) {
|
||||
this.interactiveDismissGestureBegan = false;
|
||||
if (!this.interactiveDismissGestureCancelled) {
|
||||
if (this.interactiveTransition?.began) {
|
||||
this._updateInteractiveTransition({
|
||||
began: false,
|
||||
});
|
||||
if (!this.interactiveTransition?.cancelled) {
|
||||
cleanupModalViews();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.interactiveDismissGestureCancelled) {
|
||||
if (!this.interactiveTransition?.cancelled) {
|
||||
if (typeof options.closeCallback === 'function') {
|
||||
options.closeCallback.apply(undefined, originalArgs);
|
||||
}
|
||||
@@ -431,7 +441,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
}
|
||||
};
|
||||
|
||||
if (!this.interactiveDismissGestureBegan) {
|
||||
if (!this.interactiveTransition?.began) {
|
||||
cleanupModalViews();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ let navDepth = -1;
|
||||
export class Frame extends FrameBase {
|
||||
viewController: UINavigationControllerImpl;
|
||||
_animatedDelegate = <UINavigationControllerDelegate>UINavigationControllerAnimatedDelegate.initWithOwner(new WeakRef(this));
|
||||
transitionIteractiveCtrl: UIPercentDrivenInteractiveTransition;
|
||||
transitionInteractiveCtrl: UIPercentDrivenInteractiveTransition;
|
||||
public _ios: iOSFrame;
|
||||
private _interactiveDismissGesture: (args: PanGestureEventData) => void;
|
||||
|
||||
@@ -106,10 +106,12 @@ export class Frame extends FrameBase {
|
||||
this._ios.controller.delegate = this._animatedDelegate;
|
||||
viewController[DELEGATE] = this._animatedDelegate;
|
||||
const transitionState = SharedTransition.getState(navigationTransition.instance.id);
|
||||
if (transitionState?.interactiveDismissal) {
|
||||
if (transitionState?.interactive?.dismiss) {
|
||||
this._updateInteractiveTransition({
|
||||
options: transitionState?.interactive?.dismiss,
|
||||
});
|
||||
// interactive transitions via gestures
|
||||
// TODO - these could be typed as: boolean | (view: View) => void
|
||||
// to allow users to define their own custom gesture dismissals
|
||||
// TODO - allow users to define their own custom gesture dismissals
|
||||
this._interactiveDismissGesture = this._interactiveDismissGestureHandler.bind(this);
|
||||
this.on('pan', this._interactiveDismissGesture);
|
||||
}
|
||||
@@ -198,35 +200,42 @@ export class Frame extends FrameBase {
|
||||
|
||||
private _interactiveDismissGestureHandler(args: PanGestureEventData) {
|
||||
if (args?.ios?.view) {
|
||||
this.interactiveDismissGestureBegan = true;
|
||||
this.interactiveDismissGestureCancelled = false;
|
||||
const percent = args.deltaX / (args.ios.view.bounds.size.width / 2);
|
||||
this._updateInteractiveTransition({
|
||||
began: true,
|
||||
cancelled: false,
|
||||
});
|
||||
const percent = this.interactiveTransition?.options.percentFormula ? this.interactiveTransition?.options.percentFormula(args) : args.deltaX / (args.ios.view.bounds.size.width / 2);
|
||||
if (SharedTransition.DEBUG) {
|
||||
console.log('interactive dismissal pan:', percent);
|
||||
console.log('Interactive dismissal percentage:', percent);
|
||||
}
|
||||
switch (args.state) {
|
||||
case GestureStateTypes.began:
|
||||
// const navigationContext = this.parent.page.frame._navigationQueue[0];
|
||||
// this.performGoBack(navigationContext);
|
||||
this._ios.controller.popViewControllerAnimated(true);
|
||||
// this._ios.controller.popViewControllerAnimated(true);
|
||||
this._goBackCore(this.backStack.slice(-1)[0]);
|
||||
|
||||
break;
|
||||
case GestureStateTypes.changed:
|
||||
// TODO: allow customization of threshold
|
||||
if (percent < 1) {
|
||||
if (this.transitionIteractiveCtrl) {
|
||||
this.transitionIteractiveCtrl.updateInteractiveTransition(percent);
|
||||
if (this.transitionInteractiveCtrl) {
|
||||
this.transitionInteractiveCtrl.updateInteractiveTransition(percent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GestureStateTypes.cancelled:
|
||||
case GestureStateTypes.ended:
|
||||
if (this.transitionIteractiveCtrl) {
|
||||
if (percent > 0.5) {
|
||||
this.transitionIteractiveCtrl.finishInteractiveTransition();
|
||||
if (this.transitionInteractiveCtrl) {
|
||||
const finishThreshold = isNumber(this.interactiveTransition?.options?.finishThreshold) ? this.interactiveTransition?.options?.finishThreshold : 0.5;
|
||||
if (percent > finishThreshold) {
|
||||
this.callUnloaded();
|
||||
this._tearDownUI(true);
|
||||
this.transitionInteractiveCtrl.finishInteractiveTransition();
|
||||
} else {
|
||||
this.interactiveDismissGestureCancelled = true;
|
||||
this.transitionIteractiveCtrl.cancelInteractiveTransition();
|
||||
this._updateInteractiveTransition({
|
||||
cancelled: true,
|
||||
});
|
||||
this.transitionInteractiveCtrl.cancelInteractiveTransition();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -253,7 +262,7 @@ export class Frame extends FrameBase {
|
||||
const controller = backstackEntry.resolvedPage.ios;
|
||||
const animated = this._currentEntry ? this._getIsAnimatedNavigation(this._currentEntry.entry) : false;
|
||||
|
||||
if (!this.interactiveDismissGestureCancelled) {
|
||||
if (!this.interactiveTransition?.cancelled) {
|
||||
this._updateActionBar(backstackEntry.resolvedPage);
|
||||
}
|
||||
if (Trace.isEnabled()) {
|
||||
@@ -475,9 +484,9 @@ class UINavigationControllerAnimatedDelegate extends NSObject implements UINavig
|
||||
navigationControllerInteractionControllerForAnimationController(navigationController: UINavigationController, animationController: UIViewControllerAnimatedTransitioning): UIViewControllerInteractiveTransitioning {
|
||||
const owner = this.owner?.deref();
|
||||
if (owner) {
|
||||
if (owner.interactiveDismissGestureBegan) {
|
||||
owner.transitionIteractiveCtrl = PercentInteractiveController.initWithOwner(new WeakRef(this.transition));
|
||||
return owner.transitionIteractiveCtrl;
|
||||
if (owner.interactiveTransition?.began) {
|
||||
owner.transitionInteractiveCtrl = PercentInteractiveController.initWithOwner(new WeakRef(this.transition));
|
||||
return owner.transitionInteractiveCtrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,12 +509,11 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
|
||||
}
|
||||
|
||||
startInteractiveTransition(transitionContext: UIViewControllerContextTransitioning) {
|
||||
console.log('startInteractiveTransition');
|
||||
// console.log('startInteractiveTransition');
|
||||
this.transitionContext = transitionContext;
|
||||
}
|
||||
|
||||
updateInteractiveTransition(percentComplete: number) {
|
||||
console.log('percentComplete:', percentComplete);
|
||||
const owner: any = this.owner?.deref();
|
||||
if (owner) {
|
||||
if (!this.started) {
|
||||
@@ -534,7 +542,7 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
|
||||
}
|
||||
|
||||
cancelInteractiveTransition() {
|
||||
console.log('cancelInteractiveTransition');
|
||||
// console.log('cancelInteractiveTransition');
|
||||
const owner: any = this.owner?.deref();
|
||||
if (owner && this.started) {
|
||||
const state = SharedTransition.getState(owner.id);
|
||||
@@ -562,7 +570,7 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
|
||||
}
|
||||
|
||||
finishInteractiveTransition() {
|
||||
console.log('finishInteractiveTransition');
|
||||
// console.log('finishInteractiveTransition');
|
||||
const owner: any = this.owner?.deref();
|
||||
if (owner && this.started) {
|
||||
if (this.backgroundAnimation) {
|
||||
|
||||
@@ -65,7 +65,6 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
|
||||
}
|
||||
|
||||
updateInteractiveTransition(percentComplete: number) {
|
||||
// console.log('percentComplete:', percentComplete);
|
||||
const owner = this.owner?.deref();
|
||||
if (owner) {
|
||||
if (!this.started) {
|
||||
@@ -185,7 +184,7 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim
|
||||
const { sharedElements, presented } = SharedTransition.getSharedElements(state.page, state.toPage);
|
||||
|
||||
if (SharedTransition.DEBUG) {
|
||||
console.log(' ');
|
||||
console.log(' ModalTransition: Present');
|
||||
console.log(
|
||||
`1. Found sharedTransitionTags to animate:`,
|
||||
sharedElements.map((v) => v.sharedTransitionTag)
|
||||
@@ -362,7 +361,7 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim
|
||||
// console.log('transitionContext.containerView.subviews.count:', transitionContext.containerView.subviews.count);
|
||||
|
||||
if (SharedTransition.DEBUG) {
|
||||
console.log(' ');
|
||||
console.log(' ModalTransition: Dismiss');
|
||||
console.log(
|
||||
`1. Dismiss sharedTransitionTags to animate:`,
|
||||
owner.sharedElements.presented.map((p) => p.view.sharedTransitionTag)
|
||||
|
||||
@@ -38,7 +38,7 @@ export class PageTransition extends Transition {
|
||||
const { sharedElements, presented } = SharedTransition.getSharedElements(state.page, state.toPage);
|
||||
|
||||
if (SharedTransition.DEBUG) {
|
||||
console.log(' ');
|
||||
console.log(' PageTransition: Push');
|
||||
console.log(
|
||||
`1. Found sharedTransitionTags to animate:`,
|
||||
sharedElements.map((v) => v.sharedTransitionTag)
|
||||
@@ -216,7 +216,7 @@ export class PageTransition extends Transition {
|
||||
// console.log('transitionContext.containerView.subviews.count:', transitionContext.containerView.subviews.count);
|
||||
|
||||
if (SharedTransition.DEBUG) {
|
||||
console.log(' ');
|
||||
console.log(' PageTransition: Pop');
|
||||
console.log(
|
||||
`1. Dismiss sharedTransitionTags to animate:`,
|
||||
this.sharedElements.presented.map((p) => p.view.sharedTransitionTag)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Transition } from '.';
|
||||
import { querySelectorAll, ViewBase } from '../core/view-base';
|
||||
import type { View } from '../core/view';
|
||||
import type { PanGestureEventData } from '../gestures';
|
||||
|
||||
export const DEFAULT_DURATION = 0.35;
|
||||
export const DEFAULT_SPRING = {
|
||||
@@ -12,19 +13,40 @@ export enum SharedTransitionAnimationType {
|
||||
present,
|
||||
dismiss,
|
||||
}
|
||||
export interface SharedTransitionInteractiveOptions {
|
||||
/**
|
||||
* When the pan exceeds this percentage and you let go, finish the transition.
|
||||
* Default 0.5
|
||||
*/
|
||||
finishThreshold?: number;
|
||||
/**
|
||||
* You can create your own percent formula used for determing the interactive value.
|
||||
* By default, we handle this via a formula like this for an interactive page back transition:
|
||||
* - return eventData.deltaX / (eventData.ios.view.bounds.size.width / 2);
|
||||
* @param eventData PanGestureEventData
|
||||
* @returns Should return a percentage value
|
||||
*/
|
||||
percentFormula?: (eventData: PanGestureEventData) => number;
|
||||
}
|
||||
export interface SharedTransitionConfig {
|
||||
/**
|
||||
* Page which will start the transition
|
||||
* Page which will start the transition.
|
||||
*/
|
||||
page?: ViewBase;
|
||||
/**
|
||||
* Preconfigured transition or your own custom configured one
|
||||
* Preconfigured transition or your own custom configured one.
|
||||
*/
|
||||
instance?: Transition;
|
||||
/**
|
||||
* Whether you want to allow interactive dismissal
|
||||
* Interactive transition settings. (iOS only at the moment)
|
||||
*/
|
||||
interactiveDismissal?: boolean;
|
||||
interactive?: {
|
||||
/**
|
||||
* Whether you want to allow interactive dismissal.
|
||||
* Defaults to using 'pan' gesture for dismissal however you can customize your own.
|
||||
*/
|
||||
dismiss?: SharedTransitionInteractiveOptions;
|
||||
};
|
||||
/**
|
||||
* View settings to start your transition.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user