mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 04:41:36 +08:00
feat(modal-view-ios): handle iOS 13 dismiss modal gesture (#8024)
* feat(modal-view): introduce cancelable property on ShowModalOptions * fix(modal-view): handle iOS 13 modal dismiss gesture * chore: address PR comments
This commit is contained in:

committed by
GitHub

parent
60ac4e7a05
commit
c5df258043
@ -83,10 +83,15 @@ export interface ShowModalOptions {
|
|||||||
}
|
}
|
||||||
android?: {
|
android?: {
|
||||||
/**
|
/**
|
||||||
|
* @deprecated Use ShowModalOptions.cancelable instead.
|
||||||
* An optional parameter specifying whether the modal view can be dismissed when not in full-screen mode.
|
* An optional parameter specifying whether the modal view can be dismissed when not in full-screen mode.
|
||||||
*/
|
*/
|
||||||
cancelable?: boolean
|
cancelable?: boolean
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* An optional parameter specifying whether the modal view can be dismissed when not in full-screen mode.
|
||||||
|
*/
|
||||||
|
cancelable?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class ViewBase extends Observable {
|
export abstract class ViewBase extends Observable {
|
||||||
|
@ -640,12 +640,21 @@ export class View extends ViewCommon {
|
|||||||
args.putInt(DOMID, this._domId);
|
args.putInt(DOMID, this._domId);
|
||||||
df.setArguments(args);
|
df.setArguments(args);
|
||||||
|
|
||||||
|
let cancelable = true;
|
||||||
|
|
||||||
|
if (options.android && (<any>options).android.cancelable !== undefined) {
|
||||||
|
cancelable = !!(<any>options).android.cancelable;
|
||||||
|
console.log("ShowModalOptions.android.cancelable is deprecated. Use ShowModalOptions.cancelable instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelable = options.cancelable !== undefined ? !!options.cancelable : cancelable;
|
||||||
|
|
||||||
const dialogOptions: DialogOptions = {
|
const dialogOptions: DialogOptions = {
|
||||||
owner: this,
|
owner: this,
|
||||||
fullscreen: !!options.fullscreen,
|
fullscreen: !!options.fullscreen,
|
||||||
animated: !!options.animated,
|
animated: !!options.animated,
|
||||||
stretched: !!options.stretched,
|
stretched: !!options.stretched,
|
||||||
cancelable: options.android ? !!options.android.cancelable : true,
|
cancelable: cancelable,
|
||||||
shownCallback: () => this._raiseShownModallyEvent(),
|
shownCallback: () => this._raiseShownModallyEvent(),
|
||||||
dismissCallback: () => this.closeModal()
|
dismissCallback: () => this.closeModal()
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,7 @@ export class View extends ViewCommon {
|
|||||||
nativeViewProtected: UIView;
|
nativeViewProtected: UIView;
|
||||||
viewController: UIViewController;
|
viewController: UIViewController;
|
||||||
private _popoverPresentationDelegate: ios.UIPopoverPresentationControllerDelegateImp;
|
private _popoverPresentationDelegate: ios.UIPopoverPresentationControllerDelegateImp;
|
||||||
|
private _adaptivePresentationDelegate: ios.UIAdaptivePresentationControllerDelegateImp;
|
||||||
|
|
||||||
private _isLaidOut = false;
|
private _isLaidOut = false;
|
||||||
private _hasTransfrom = false;
|
private _hasTransfrom = false;
|
||||||
@ -422,14 +423,19 @@ export class View extends ViewCommon {
|
|||||||
controller.modalPresentationStyle = presentationStyle;
|
controller.modalPresentationStyle = presentationStyle;
|
||||||
|
|
||||||
if (presentationStyle === UIModalPresentationStyle.Popover) {
|
if (presentationStyle === UIModalPresentationStyle.Popover) {
|
||||||
const popoverPresentationController = controller.popoverPresentationController;
|
this._setupPopoverControllerDelegate(controller, parent);
|
||||||
this._popoverPresentationDelegate = ios.UIPopoverPresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback);
|
}
|
||||||
popoverPresentationController.delegate = this._popoverPresentationDelegate;
|
}
|
||||||
const view = parent.nativeViewProtected;
|
|
||||||
// Note: sourceView and sourceRect are needed to specify the anchor location for the popover.
|
const cancelable = options.cancelable !== undefined ? !!options.cancelable : true;
|
||||||
// Note: sourceView should be the button triggering the modal. If it the Page the popover might appear "behind" the page content
|
|
||||||
popoverPresentationController.sourceView = view;
|
if (majorVersion >= 13) {
|
||||||
popoverPresentationController.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
|
if (cancelable) {
|
||||||
|
// Listen for dismiss modal callback.
|
||||||
|
this._setupAdaptiveControllerDelegate(controller);
|
||||||
|
} else {
|
||||||
|
// Prevent users from dismissing the modal.
|
||||||
|
(<any>controller).modalInPresentation = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,6 +650,22 @@ export class View extends ViewCommon {
|
|||||||
backgroundInternal.hasBorderWidth() ||
|
backgroundInternal.hasBorderWidth() ||
|
||||||
backgroundInternal.hasBorderRadius();
|
backgroundInternal.hasBorderRadius();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _setupPopoverControllerDelegate(controller: UIViewController, parent: View) {
|
||||||
|
const popoverPresentationController = controller.popoverPresentationController;
|
||||||
|
this._popoverPresentationDelegate = ios.UIPopoverPresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback);
|
||||||
|
popoverPresentationController.delegate = this._popoverPresentationDelegate;
|
||||||
|
const view = parent.nativeViewProtected;
|
||||||
|
// Note: sourceView and sourceRect are needed to specify the anchor location for the popover.
|
||||||
|
// Note: sourceView should be the button triggering the modal. If it the Page the popover might appear "behind" the page content
|
||||||
|
popoverPresentationController.sourceView = view;
|
||||||
|
popoverPresentationController.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setupAdaptiveControllerDelegate(controller: UIViewController) {
|
||||||
|
this._adaptivePresentationDelegate = ios.UIAdaptivePresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback);
|
||||||
|
controller.presentationController.delegate = this._adaptivePresentationDelegate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
View.prototype._nativeBackgroundState = "unset";
|
View.prototype._nativeBackgroundState = "unset";
|
||||||
|
|
||||||
@ -1019,6 +1041,28 @@ export namespace ios {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UIAdaptivePresentationControllerDelegateImp extends NSObject implements UIAdaptivePresentationControllerDelegate {
|
||||||
|
public static ObjCProtocols = [UIAdaptivePresentationControllerDelegate];
|
||||||
|
|
||||||
|
private owner: WeakRef<View>;
|
||||||
|
private closedCallback: Function;
|
||||||
|
|
||||||
|
public static initWithOwnerAndCallback(owner: WeakRef<View>, whenClosedCallback: Function): UIAdaptivePresentationControllerDelegateImp {
|
||||||
|
const instance = <UIAdaptivePresentationControllerDelegateImp>super.new();
|
||||||
|
instance.owner = owner;
|
||||||
|
instance.closedCallback = whenClosedCallback;
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public presentationControllerDidDismiss(presentationController: UIPresentationController) {
|
||||||
|
const owner = this.owner.get();
|
||||||
|
if (owner && typeof this.closedCallback === "function") {
|
||||||
|
this.closedCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class UIPopoverPresentationControllerDelegateImp extends NSObject implements UIPopoverPresentationControllerDelegate {
|
export class UIPopoverPresentationControllerDelegateImp extends NSObject implements UIPopoverPresentationControllerDelegate {
|
||||||
public static ObjCProtocols = [UIPopoverPresentationControllerDelegate];
|
public static ObjCProtocols = [UIPopoverPresentationControllerDelegate];
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user