mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(ios): page transition handling with more flexibility
This commit is contained in:
1
packages/core/accessibility/index.d.ts
vendored
1
packages/core/accessibility/index.d.ts
vendored
@@ -1,4 +1,5 @@
|
||||
import type { Page } from '../ui/page';
|
||||
import type { ViewBase } from '../ui/core/view-base';
|
||||
import type { View } from '../ui/core/view';
|
||||
import type { AndroidAccessibilityEvent } from './accessibility-types';
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as Application from '../application';
|
||||
import type { ViewBase } from '../ui/core/view-base';
|
||||
import type { View } from '../ui/core/view';
|
||||
import { notifyAccessibilityFocusState } from './accessibility-common';
|
||||
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait } from './accessibility-types';
|
||||
@@ -120,7 +121,7 @@ function ensureNativeClasses() {
|
||||
});
|
||||
}
|
||||
|
||||
export function setupAccessibleView(view: View): void {
|
||||
export function setupAccessibleView(view: Partial<ViewBase>): void {
|
||||
const uiView = view.nativeViewProtected as UIView;
|
||||
if (!uiView) {
|
||||
return;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
// Definitions.
|
||||
import { AlignSelf, FlexGrow, FlexShrink, FlexWrapBefore, Order } from '../../layouts/flexbox-layout';
|
||||
import { Page } from '../../page';
|
||||
|
||||
// Types.
|
||||
import { CoreTypes } from '../../../core-types';
|
||||
import { Property, CssProperty, CssAnimationProperty, InheritedProperty, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, initNativeView } from '../properties';
|
||||
import { setupAccessibleView } from '../../../accessibility';
|
||||
import { CSSUtils } from '../../../css/system-classes';
|
||||
import { Source } from '../../../utils/debug';
|
||||
import { Binding, BindingOptions } from '../bindable';
|
||||
@@ -442,6 +440,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
|
||||
return true;
|
||||
});
|
||||
setupAccessibleView(this);
|
||||
|
||||
this._emit('loaded');
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import { AndroidActivityBackPressedEventData, android as androidApp } from '../.
|
||||
import { Device } from '../../../platform';
|
||||
import lazy from '../../../utils/lazy';
|
||||
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties';
|
||||
import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, setupAccessibleView, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility';
|
||||
import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility';
|
||||
import * as Utils from '../../../utils';
|
||||
import { SDK_VERSION } from '../../../utils/constants';
|
||||
import { CSSShadow } from '../../styling/css-shadow';
|
||||
@@ -320,20 +320,6 @@ export class View extends ViewCommon {
|
||||
|
||||
nativeViewProtected: android.view.View;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const weakRef = new WeakRef(this);
|
||||
const handler = () => {
|
||||
const owner = weakRef.get();
|
||||
if (owner) {
|
||||
setupAccessibleView(owner);
|
||||
owner.off(View.loadedEvent, handler);
|
||||
}
|
||||
};
|
||||
this.on(View.loadedEvent, handler);
|
||||
}
|
||||
|
||||
// TODO: Implement unobserve that detach the touchListener.
|
||||
_observe(type: GestureTypes, callback: (args: GestureEventData) => void, thisArg?: any): void {
|
||||
super._observe(type, callback, thisArg);
|
||||
|
||||
@@ -11,7 +11,7 @@ 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';
|
||||
import { profile } from '../../../profiling';
|
||||
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
|
||||
import { setupAccessibleView, IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties, AccessibilityEventOptions, AccessibilityRole, AccessibilityState } from '../../../accessibility';
|
||||
import { IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties, AccessibilityEventOptions, AccessibilityRole, AccessibilityState } from '../../../accessibility';
|
||||
import { CoreTypes } from '../../../core-types';
|
||||
|
||||
export * from './view-common';
|
||||
@@ -58,12 +58,6 @@ export class View extends ViewCommon implements ViewDefinition {
|
||||
return (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.once(View.loadedEvent, () => setupAccessibleView(this));
|
||||
}
|
||||
|
||||
disposeNativeView() {
|
||||
super.disposeNativeView();
|
||||
|
||||
|
||||
@@ -5,18 +5,6 @@ import { FadeTransition } from '../transition/fade-transition';
|
||||
|
||||
import { Trace } from '../../trace';
|
||||
|
||||
namespace UIViewControllerAnimatedTransitioningMethods {
|
||||
const methodSignature = NSMethodSignature.signatureWithObjCTypes('v@:c');
|
||||
const invocation = NSInvocation.invocationWithMethodSignature(methodSignature);
|
||||
invocation.selector = 'completeTransition:';
|
||||
|
||||
export function completeTransition(didComplete: boolean) {
|
||||
const didCompleteReference = new interop.Reference(interop.types.bool, didComplete);
|
||||
invocation.setArgumentAtIndex(didCompleteReference, 2);
|
||||
invocation.invokeWithTarget(this);
|
||||
}
|
||||
}
|
||||
|
||||
@NativeClass
|
||||
class AnimatedTransitioning extends NSObject implements UIViewControllerAnimatedTransitioning {
|
||||
public static ObjCProtocols = [UIViewControllerAnimatedTransitioning];
|
||||
@@ -37,9 +25,7 @@ class AnimatedTransitioning extends NSObject implements UIViewControllerAnimated
|
||||
return impl;
|
||||
}
|
||||
|
||||
public animateTransition(transitionContext: any): void {
|
||||
const containerView = transitionContext.valueForKey('containerView');
|
||||
const completion = UIViewControllerAnimatedTransitioningMethods.completeTransition.bind(transitionContext);
|
||||
public animateTransition(transitionContext: UIViewControllerContextTransitioning): void {
|
||||
switch (this._operation) {
|
||||
case UINavigationControllerOperation.Push:
|
||||
this._transitionType = 'push';
|
||||
@@ -55,7 +41,7 @@ class AnimatedTransitioning extends NSObject implements UIViewControllerAnimated
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`START ${this._transition} ${this._transitionType}`, Trace.categories.Transition);
|
||||
}
|
||||
this._transition.animateIOSTransition(containerView, this._fromVC.view, this._toVC.view, this._operation, completion);
|
||||
this._transition.animateIOSTransition(transitionContext, this._fromVC, this._toVC, this._operation);
|
||||
}
|
||||
|
||||
public transitionDuration(transitionContext: UIViewControllerContextTransitioning): number {
|
||||
@@ -85,7 +71,7 @@ export function _createIOSAnimatedTransitioning(navigationTransition: Navigation
|
||||
} else if (navigationTransition.name) {
|
||||
const name = navigationTransition.name.toLowerCase();
|
||||
if (name.indexOf('slide') === 0) {
|
||||
const direction = name.substr('slide'.length) || 'left'; //Extract the direction from the string
|
||||
const direction = name.substring('slide'.length) || 'left'; //Extract the direction from the string
|
||||
transition = new SlideTransition(direction, navigationTransition.duration, nativeCurve);
|
||||
} else if (name === 'fade') {
|
||||
transition = new FadeTransition(navigationTransition.duration, nativeCurve);
|
||||
|
||||
@@ -170,17 +170,18 @@ export class ScrollView extends ScrollViewBase {
|
||||
}
|
||||
|
||||
public onLayout(left: number, top: number, right: number, bottom: number): void {
|
||||
if (!this.nativeViewProtected) {
|
||||
return;
|
||||
}
|
||||
const insets = this.getSafeAreaInsets();
|
||||
let width = right - left - insets.right - insets.left;
|
||||
let height = bottom - top - insets.bottom - insets.top;
|
||||
|
||||
const nativeView = this.nativeViewProtected;
|
||||
|
||||
if (majorVersion > 10) {
|
||||
// Disable automatic adjustment of scroll view insets
|
||||
// Consider exposing this as property with all 4 modes
|
||||
// https://developer.apple.com/documentation/uikit/uiscrollview/contentinsetadjustmentbehavior
|
||||
nativeView.contentInsetAdjustmentBehavior = 2;
|
||||
this.nativeViewProtected.contentInsetAdjustmentBehavior = 2;
|
||||
}
|
||||
|
||||
let scrollWidth = width + insets.left + insets.right;
|
||||
@@ -193,7 +194,7 @@ export class ScrollView extends ScrollViewBase {
|
||||
height = Math.max(this._contentMeasuredHeight, height);
|
||||
}
|
||||
|
||||
nativeView.contentSize = CGSizeMake(layout.toDeviceIndependentPixels(scrollWidth), layout.toDeviceIndependentPixels(scrollHeight));
|
||||
this.nativeViewProtected.contentSize = CGSizeMake(layout.toDeviceIndependentPixels(scrollWidth), layout.toDeviceIndependentPixels(scrollHeight));
|
||||
View.layoutChild(this, this.layoutView, insets.left, insets.top, insets.left + width, insets.top + height);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Transition } from '.';
|
||||
|
||||
export class FadeTransition extends Transition {
|
||||
public animateIOSTransition(containerView: UIView, fromView: UIView, toView: UIView, operation: UINavigationControllerOperation, completion: (finished: boolean) => void): void {
|
||||
public animateIOSTransition(transitionContext: UIViewControllerContextTransitioning, fromViewCtrl: UIViewController, toViewCtrl: UIViewController, operation: UINavigationControllerOperation): void {
|
||||
const toView = toViewCtrl.view;
|
||||
const originalToViewAlpha = toView.alpha;
|
||||
const fromView = fromViewCtrl.view;
|
||||
const originalFromViewAlpha = fromView.alpha;
|
||||
|
||||
toView.alpha = 0.0;
|
||||
@@ -10,10 +12,10 @@ export class FadeTransition extends Transition {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -29,7 +31,7 @@ export class FadeTransition extends Transition {
|
||||
(finished: boolean) => {
|
||||
toView.alpha = originalToViewAlpha;
|
||||
fromView.alpha = originalFromViewAlpha;
|
||||
completion(finished);
|
||||
transitionContext.completeTransition(finished);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export class Transition {
|
||||
private _interpolator: android.view.animation.Interpolator;
|
||||
private _id: number;
|
||||
|
||||
constructor(duration: number, curve: any) {
|
||||
constructor(duration: number, curve?: any) {
|
||||
this._duration = duration;
|
||||
this._interpolator = curve ? _resolveAnimationCurve(curve) : _defaultInterpolator();
|
||||
this._id = transitionId++;
|
||||
@@ -30,7 +30,7 @@ export class Transition {
|
||||
return this._interpolator;
|
||||
}
|
||||
|
||||
public animateIOSTransition(containerView: any, fromView: any, toView: any, operation: any, completion: (finished: boolean) => void): void {
|
||||
public animateIOSTransition(transitionContext: any, fromViewCtrl: any, toViewCtrl: any, operation: any): void {
|
||||
throw new Error('Abstract method call');
|
||||
}
|
||||
|
||||
|
||||
4
packages/core/ui/transition/index.d.ts
vendored
4
packages/core/ui/transition/index.d.ts
vendored
@@ -1,9 +1,9 @@
|
||||
export class Transition {
|
||||
static AndroidTransitionType: { enter: string; exit: string; popEnter: string; popExit: string };
|
||||
constructor(duration: number, nativeCurve: any);
|
||||
constructor(duration: number, nativeCurve?: any /* UIViewAnimationCurve | string | CubicBezierAnimationCurve | android.view.animation.Interpolator | android.view.animation.LinearInterpolator */);
|
||||
public getDuration(): number;
|
||||
public getCurve(): any;
|
||||
public animateIOSTransition(containerView: any, fromView: any, toView: any, operation: any, completion: (finished: boolean) => void): void;
|
||||
public animateIOSTransition(transitionContext: any /*UIViewControllerContextTransitioning */, fromViewCtrl: any /* UIViewController */, toViewCtrl: any /* UIViewController */, operation: any /* UINavigationControllerOperation */): void;
|
||||
public createAndroidAnimator(transitionType: string): any;
|
||||
public toString(): string;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export class Transition {
|
||||
return this._curve;
|
||||
}
|
||||
|
||||
public animateIOSTransition(containerView: UIView, fromView: UIView, toView: UIView, operation: UINavigationControllerOperation, completion: (finished: boolean) => void): void {
|
||||
public animateIOSTransition(transitionContext: UIViewControllerContextTransitioning, fromViewCtrl: UIViewController, toViewCtrl: UIViewController, operation: UINavigationControllerOperation): void {
|
||||
throw new Error('Abstract method call');
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@ export class SlideTransition extends Transition {
|
||||
this._direction = direction;
|
||||
}
|
||||
|
||||
public animateIOSTransition(containerView: UIView, fromView: UIView, toView: UIView, operation: UINavigationControllerOperation, completion: (finished: boolean) => void): void {
|
||||
public animateIOSTransition(transitionContext: UIViewControllerContextTransitioning, fromViewCtrl: UIViewController, toViewCtrl: UIViewController, operation: UINavigationControllerOperation): void {
|
||||
const toView = toViewCtrl.view;
|
||||
const originalToViewTransform = toView.transform;
|
||||
const fromView = fromViewCtrl.view;
|
||||
const originalFromViewTransform = fromView.transform;
|
||||
|
||||
let fromViewEndTransform: CGAffineTransform;
|
||||
@@ -46,10 +48,10 @@ export class SlideTransition extends Transition {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -65,7 +67,7 @@ export class SlideTransition extends Transition {
|
||||
(finished: boolean) => {
|
||||
toView.transform = originalToViewTransform;
|
||||
fromView.transform = originalFromViewTransform;
|
||||
completion(finished);
|
||||
transitionContext.completeTransition(finished);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2606,7 +2606,7 @@ export interface TraceWriter {
|
||||
export class Transition {
|
||||
constructor(duration: number, nativeCurve: any);
|
||||
// (undocumented)
|
||||
public animateIOSTransition(containerView: any, fromView: any, toView: any, operation: any, completion: (finished: boolean) => void): void;
|
||||
public animateIOSTransition(transitionContext: UIViewControllerContextTransitioning, fromViewCtrl: UIViewController, toViewCtrl: UIViewController, operation: UINavigationControllerOperation): void;
|
||||
// (undocumented)
|
||||
public createAndroidAnimator(transitionType: string): any;
|
||||
// (undocumented)
|
||||
|
||||
Reference in New Issue
Block a user