nativescript-ui-sidedrawer
Version:
Add additional space to your app. Use it for navigation or custom content. Slides in from all four sides of the screen.
409 lines • 17.9 kB
JavaScript
export * from './common';
import * as commonModule from './common';
import { View, Utils, IOSHelper } from '@nativescript/core';
////////////////////////////////////////////////
export class RadSideDrawer extends commonModule.RadSideDrawer {
constructor() {
super();
let screen = UIScreen.mainScreen;
this._ios = TKSideDrawerView.alloc().initWithFrame(screen.bounds);
this._nativeDelegate = TKSideDrawerDelegateImpl.initWithOwner(this);
this._ios.defaultSideDrawer.width = this.drawerContentSize;
this._ios.defaultSideDrawer.style.blurType = 0;
this._ios.defaultSideDrawer.headerView = null;
this._ios.defaultSideDrawer.footerView = null;
this._ios.defaultSideDrawer.delegate = this._nativeDelegate;
this.setShadowColor(this.shadowColor);
}
// @ts-ignore
get ios() {
return this._ios;
}
createNativeView() {
if (!this._isRootView) {
this.page.on('navigatingFrom', this.onNavigatingFrom, this);
}
return this.ios;
}
disposeNativeView() {
if (!this._isRootView) {
this.page.off('navigatingFrom', this.onNavigatingFrom, this);
}
}
onNavigatingFrom(args) {
if (this.getIsOpen()) {
this.closeDrawer();
}
}
bringMainContentOnTop() {
this._ios.defaultSideDrawer.superview.bringSubviewToFront(this._ios.defaultSideDrawer);
this.viewController.view.bringSubviewToFront(this._ios.hostview);
}
reattachGestures() {
if (!this.mainContent && !this.mainContent.viewController && !this.mainContent.viewController.view && !this.mainContent.viewController.view.superview && !this.mainContent.viewController.view.superview.superview) {
console.log('Error: No `this.mainContent` found. Cannot attach gestures to RadSideDrawer.');
return;
}
// We need to reattach the gestures since we have manipulated the native view hierarchy in `_addViewToNativeVisualTree`
this._ios.defaultSideDrawer.detachGesturesFromView(this.nativeViewProtected);
this._ios.defaultSideDrawer.attachGesturesToView(this.mainContent.viewController.view.superview.superview);
}
isRootDrawer() {
return this.viewController && this.viewController.view;
}
onUnloaded() {
super.onUnloaded();
}
// data changed event handlers
_onDrawerLocationChanged(oldValue, newValue) {
if (!newValue) {
return;
}
this.setDrawerLocation(newValue);
}
_onShadowColorChanged(oldValue, newValue) {
this.setShadowColor(newValue);
}
setShadowColor(color) {
this._ios.defaultSideDrawer.style.shadowMode = 2;
this._ios.defaultSideDrawer.style.dimOpacity = 0.42;
this._ios.defaultSideDrawer.style.shadowRadius = 0;
this._ios.defaultSideDrawer.style.shadowOpacity = 1; // 0-1, higher is darker
this._ios.defaultSideDrawer.style.shadowColor = color ? color.ios : RadSideDrawer.shadowColorProperty.defaultValue.ios;
}
_onGesturesEnabledChanged(oldValue, newValue) {
let value = newValue;
this.ios.defaultSideDrawer.allowGestures = value;
}
_onAllowEdgeSwipeChanged(oldValue, newValue) {
let value = newValue;
this.ios.defaultSideDrawer.allowEdgeSwipe = value;
}
setDrawerLocation(newLocation) {
switch (newLocation) {
case commonModule.SideDrawerLocation.Left:
this._ios.defaultSideDrawer.position = 0 /* TKSideDrawerPosition.Left */;
break;
case commonModule.SideDrawerLocation.Right:
this._ios.defaultSideDrawer.position = 1 /* TKSideDrawerPosition.Right */;
break;
case commonModule.SideDrawerLocation.Top:
this._ios.defaultSideDrawer.position = 2 /* TKSideDrawerPosition.Top */;
break;
case commonModule.SideDrawerLocation.Bottom:
this._ios.defaultSideDrawer.position = 3 /* TKSideDrawerPosition.Bottom */;
break;
}
this.requestLayout();
}
_onDrawerContentSizeChanged(oldValue, newValue) {
let value = newValue;
this._ios.defaultSideDrawer.width = value;
}
_onDrawerTransitionChanged(oldValue, newValue) {
let value = newValue;
let finalVal;
if (typeof value === 'string') {
switch (value.toLowerCase()) {
case commonModule.FadeTransitionString: {
finalVal = new FadeTransition();
break;
}
case commonModule.PushTransitionString: {
finalVal = new PushTransition();
break;
}
case commonModule.RevealTransitionString: {
finalVal = new RevealTransition();
break;
}
case commonModule.ReverseSlideOutTransitionString: {
finalVal = new ReverseSlideOutTransition();
break;
}
case commonModule.ScaleDownPusherTransitionString: {
finalVal = new ScaleDownPusherTransition();
break;
}
case commonModule.ScaleUpTransitionString: {
finalVal = new ScaleUpTransition();
break;
}
case commonModule.SlideAlongTransitionString: {
finalVal = new SlideAlongTransition();
break;
}
case commonModule.SlideInOnTopTransitionString: {
finalVal = new SlideInOnTopTransition();
break;
}
default: {
console.log('Error: Not supported value (' + value + ") set to 'drawerTransition'");
finalVal = new SlideInOnTopTransition();
break;
}
}
if (this.drawerTransition !== finalVal) {
this.drawerTransition = finalVal;
return;
}
}
else {
finalVal = value;
}
this._ios.defaultSideDrawer.transition = finalVal.getNativeContent();
}
get _nativeView() {
return this._ios;
}
closeDrawer() {
if (this._ios) {
this._ios.defaultSideDrawer.dismiss();
super.closeDrawer();
}
}
showDrawer() {
if (this._ios) {
this._ios.defaultSideDrawer.show();
super.showDrawer();
}
}
eachChildView(callback) {
const mainContent = this.mainContent;
if (mainContent) {
callback(mainContent);
}
if (this.drawerContent) {
callback(this.drawerContent);
}
}
onLayout(left, top, right, bottom) {
// In the case where the RadSideDrawer is not root view of the app
// it doesn't have a viewController and childViewControllers. In this case
// the RadSideDrawer must lay out its children drawerContent and mainContent
if (!this.viewController) {
// need setTimeout to allow the children get correct safeAreaInsets
setTimeout(() => {
let width = right - left;
let height = bottom - top;
let screenWidth = width;
let screenHeight = height;
let screen = UIScreen.mainScreen;
let drawerSize = Utils.layout.toDevicePixels(this.drawerContentSize);
let insets = this.getSafeAreaInsets();
let pos = this._ios.defaultSideDrawer.position;
switch (pos) {
case 2 /* TKSideDrawerPosition.Top */:
this.drawerContent.layout(0, 0, right, drawerSize + insets.top);
break;
case 3 /* TKSideDrawerPosition.Bottom */:
this.drawerContent.layout(0, bottom - drawerSize - insets.bottom, right, bottom);
break;
case 0 /* TKSideDrawerPosition.Left */:
this.drawerContent.layout(0, 0, drawerSize + insets.left, bottom);
break;
case 1 /* TKSideDrawerPosition.Right */:
this.drawerContent.layout(0, 0, drawerSize + insets.right, bottom);
break;
}
this.mainContent.layout(0, 0, width, height);
});
}
else {
// TODO: Investigate if this cannot be resolved in tns-core-modules UILayoutViewController, if it can remove this code
// We need to move the `mainContent` and `drawerContent native view to the root UIViewController in order for the safe areas to be updated when 'in-call' status bar is toggled.
// We also need to move the gesture handlers to the new views.
// Related to issue https://github.com/NativeScript/nativescript-ui-feedback/issues/1189
if (this.areViewsRearranged) {
this.areViewsRearranged = false;
this.bringMainContentOnTop();
this.reattachGestures();
}
}
}
onMeasure(widthMeasureSpec, heightMeasureSpec) {
let pos = this._ios.defaultSideDrawer.position;
let drawerWidth = widthMeasureSpec;
let drawerHeight = heightMeasureSpec;
// need to manually handle the safe inset if it's not root side drawer
let drawerSize = Utils.layout.toDevicePixels(this.drawerContentSize);
if (!this.viewController) {
const insets = this.getSafeAreaInsets();
switch (pos) {
case 2 /* TKSideDrawerPosition.Top */:
drawerSize -= insets.top;
break;
case 3 /* TKSideDrawerPosition.Bottom */:
drawerSize -= insets.bottom;
break;
case 0 /* TKSideDrawerPosition.Left */:
drawerSize -= insets.left;
break;
case 1 /* TKSideDrawerPosition.Right */:
drawerSize -= insets.right;
break;
}
}
if (pos === 2 /* TKSideDrawerPosition.Top */ || pos === 3 /* TKSideDrawerPosition.Bottom */) {
View.measureChild(this, this.drawerContent, drawerWidth, Utils.layout.makeMeasureSpec(drawerSize, Utils.layout.EXACTLY));
}
else {
View.measureChild(this, this.drawerContent, Utils.layout.makeMeasureSpec(drawerSize, Utils.layout.EXACTLY), drawerHeight);
}
let result = View.measureChild(this, this.mainContent, widthMeasureSpec, heightMeasureSpec);
let width = Utils.layout.getMeasureSpecSize(widthMeasureSpec);
let widthMode = Utils.layout.getMeasureSpecMode(widthMeasureSpec);
let height = Utils.layout.getMeasureSpecSize(heightMeasureSpec);
let heightMode = Utils.layout.getMeasureSpecMode(heightMeasureSpec);
let widthAndState = View.resolveSizeAndState(result.measuredWidth, width, widthMode, 0);
let heightAndState = View.resolveSizeAndState(result.measuredHeight, height, heightMode, 0);
this.setMeasuredDimension(widthAndState, heightAndState);
}
_addViewToNativeVisualTree(child, atIndex) {
super._addViewToNativeVisualTree(child, atIndex);
this.areViewsRearranged = true;
const controller = this.viewController;
let content = child.nativeViewProtected;
if (controller && !child.viewController) {
child.viewController = IOSHelper.UILayoutViewController.initWithOwner(new WeakRef(child));
const view = child.viewController.view;
view.addSubview(child.nativeViewProtected);
content = view;
}
const childController = child.viewController;
if (controller && childController) {
controller.addChildViewController(childController);
}
if (child === this.mainContent) {
if (this.isRootDrawer() && childController) {
// TODO: Investigate if this cannot be resolved in tns-core-modules UILayoutViewController, if it can remove this code
// We need to move the `mainContent` native view to the root UIViewController in order for the safe areas to be updated when 'in-call' status bar is toggled.
// Related to issue https://github.com/NativeScript/nativescript-ui-feedback/issues/1189
this._ios.setMainView(childController.view);
controller.view.addSubview(this._ios.hostview);
}
else {
this._ios.setMainView(content);
}
}
else if (child === this.drawerContent) {
this._ios.defaultSideDrawer.content = content;
if (controller && childController) {
// TODO: Investigate if this cannot be resolved in tns-core-modules UILayoutViewController, if it can remove this code
// We need to move the `drawerContent` native view to the root UIViewController in order for the safe areas to be updated when 'in-call' status bar is toggled.
// Related to issue https://github.com/NativeScript/nativescript-ui-feedback/issues/1189
controller.view.addSubview(this._ios.defaultSideDrawer);
}
}
return true;
}
}
////////////////////////////////////////////////
// TRANSITIONS
////////////////////////////////////////////////
export class FadeTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 6 /* TKSideDrawerTransitionType.FadeIn */;
}
}
export class PushTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 2 /* TKSideDrawerTransitionType.Push */;
}
}
export class RevealTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 1 /* TKSideDrawerTransitionType.Reveal */;
}
}
export class ReverseSlideOutTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 4 /* TKSideDrawerTransitionType.ReverseSlideOut */;
}
}
export class ScaleDownPusherTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 7 /* TKSideDrawerTransitionType.ScaleDownPusher */;
}
}
export class ScaleUpTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 5 /* TKSideDrawerTransitionType.ScaleUp */;
}
}
export class SlideAlongTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 3 /* TKSideDrawerTransitionType.SlideAlong */;
}
}
export class SlideInOnTopTransition extends commonModule.DrawerTransitionBase {
getNativeContent() {
return 0 /* TKSideDrawerTransitionType.SlideInOnTop */;
}
}
var TKSideDrawerDelegateImpl = /** @class */ (function (_super) {
__extends(TKSideDrawerDelegateImpl, _super);
function TKSideDrawerDelegateImpl() {
return _super !== null && _super.apply(this, arguments) || this;
}
TKSideDrawerDelegateImpl.initWithOwner = function (owner) {
var delegate = new TKSideDrawerDelegateImpl();
delegate._owner = new WeakRef(owner);
return delegate;
};
TKSideDrawerDelegateImpl.prototype.willShowSideDrawer = function (sideDrawer) {
var owner = this._owner.get();
if (owner && owner.hasListeners(commonModule.RadSideDrawer.drawerOpeningEvent)) {
var args = {
eventName: commonModule.RadSideDrawer.drawerOpeningEvent,
object: owner,
returnValue: false
};
owner.notify(args);
}
};
TKSideDrawerDelegateImpl.prototype.didShowSideDrawer = function (sideDrawer) {
var owner = this._owner.get();
if (owner && owner.hasListeners(commonModule.RadSideDrawer.drawerOpenedEvent)) {
var args = {
eventName: commonModule.RadSideDrawer.drawerOpenedEvent,
object: owner
};
owner.notify(args);
}
};
TKSideDrawerDelegateImpl.prototype.willDismissSideDrawer = function (sideDrawer) {
var owner = this._owner.get();
if (owner && owner.hasListeners(commonModule.RadSideDrawer.drawerClosingEvent)) {
var args = {
eventName: commonModule.RadSideDrawer.drawerClosingEvent,
object: owner,
returnValue: false
};
owner.notify(args);
}
};
TKSideDrawerDelegateImpl.prototype.didDismissSideDrawer = function (sideDrawer) {
var owner = this._owner.get();
if (owner && owner.hasListeners(commonModule.RadSideDrawer.drawerClosedEvent)) {
var args = {
eventName: commonModule.RadSideDrawer.drawerClosedEvent,
object: owner
};
owner.notify(args);
}
};
TKSideDrawerDelegateImpl.prototype.didPanSideDrawer = function (sideDrawer) {
var owner = this._owner.get();
if (owner && owner.hasListeners(commonModule.RadSideDrawer.drawerPanEvent)) {
var args = {
eventName: commonModule.RadSideDrawer.drawerPanEvent,
object: owner
};
owner.notify(args);
}
};
TKSideDrawerDelegateImpl.ObjCProtocols = [TKSideDrawerDelegate];
return TKSideDrawerDelegateImpl;
}(NSObject));
//# sourceMappingURL=index.ios.js.map