UNPKG

@nativescript/keyboard-toolbar

Version:
139 lines 7.25 kB
import { Application, Screen, EditableTextBase, CoreTypes, Page, Frame } from '@nativescript/core'; import { ToolbarBase } from './common'; export class Toolbar extends ToolbarBase { _loaded() { this.keyboardNotificationObserver = Application.ios.addNotificationObserver(UIKeyboardWillChangeFrameNotification, (notification) => { const newKeyboardHeight = notification.userInfo.valueForKey(UIKeyboardFrameEndUserInfoKey).CGRectValue.size.height; if (newKeyboardHeight === this.lastKeyboardHeight) { return; } const isFirstAnimation = this.lastKeyboardHeight === undefined; this.lastKeyboardHeight = newKeyboardHeight; if (!isFirstAnimation && this.hasFocus) { const parent = this.content.parent; parent.translateY = this.startPositionY - newKeyboardHeight - this.lastHeight / Screen.mainScreen.scale; } }); const onViewForIdFound = (forView) => { const parent = this.content.parent; // experimental support for non-text widgets.. but not sure if this is useful, so not documenting it yet const isText = forView instanceof EditableTextBase; const hasIQKeyboardManagerInstalled = typeof IQKeyboardManager !== 'undefined'; const iqKeyboardManagerOriginalDistance = hasIQKeyboardManagerInstalled ? IQKeyboardManager.sharedManager().keyboardDistanceFromTextField : 0; if (isText) { forView.on('focus', () => { if (hasIQKeyboardManagerInstalled) { IQKeyboardManager.sharedManager().keyboardDistanceFromTextField = iqKeyboardManagerOriginalDistance + parent.height; } this.hasFocus = true; // wrap in a timeout, to make sure this runs after 'UIKeyboardWillChangeFrameNotification' setTimeout(() => { const animateToY = this.startPositionY - this.lastKeyboardHeight - (this.showWhenKeyboardHidden === true ? 0 : this.lastHeight / Screen.mainScreen.scale); this.log('focus, animateToY: ' + animateToY); parent .animate({ translate: { x: 0, y: animateToY }, // see http://cubic-bezier.com/#.17,.67,.69,1.04 curve: CoreTypes.AnimationCurve.cubicBezier(0.32, 0.49, 0.56, 1), duration: 370, }) .then(() => { }); }); }); forView.on('blur', () => { if (hasIQKeyboardManagerInstalled) { IQKeyboardManager.sharedManager().keyboardDistanceFromTextField = iqKeyboardManagerOriginalDistance; } this.hasFocus = false; const animateToY = this.showWhenKeyboardHidden === true && this.showAtBottomWhenKeyboardHidden !== true ? 0 : this.startPositionY; this.log('blur, animateToY: ' + animateToY); parent .animate({ translate: { x: 0, y: animateToY }, curve: CoreTypes.AnimationCurve.cubicBezier(0.32, 0.49, 0.56, 1), duration: 370, }) .then(() => { }); }); } else { // it's not a text widget, so just animate the toolbar forView.on('tap', () => { const animateToY = this.startPositionY - this.lastHeight / Screen.mainScreen.scale; this.log('tap, animateToY: ' + animateToY); parent .animate({ translate: { x: 0, y: animateToY }, // see http://cubic-bezier.com/#.17,.67,.69,1.04 curve: CoreTypes.AnimationCurve.cubicBezier(0.32, 0.49, 0.56, 1), duration: 370, }) .then(() => { }); }); } }; // TODO this can be reused on Android (but I haven't seen the underlying issue there (yet)) this.getViewForId(10) .then((view) => onViewForIdFound(view)) .catch(() => console.log(`\n⌨ ⌨ ⌨ Please make sure forId="<view id>" resolves to a visible view, or the toolbar won't render correctly! Example: <Toolbar forId="myId" height="44">\n\n`)); } // depending on the framework (looking at you, Angular!) it may take longer to find the view, so here we try to get it asap (instead of a fixed 1sec timeout for instance) getViewForId(attemptsLeft) { return new Promise((resolve, reject) => { if (attemptsLeft-- > 0) { setTimeout(() => { let pg; if (Frame.topmost()) { pg = Frame.topmost().currentPage; } else { pg = this.content.parent; while (pg && !(pg instanceof Page)) { pg = pg.parent; } } const page = pg; const found = page && page.modal ? page.modal.getViewById(this.forId) : page && page.getViewById(this.forId); if (found) { resolve(found); } else { this.getViewForId(attemptsLeft).then(resolve).catch(reject); } }, 200); } else { reject(); } }); } _unloaded() { Application.ios.removeNotificationObserver(this.keyboardNotificationObserver, UIKeyboardWillChangeFrameNotification); } _layout(left, top, right, bottom) { const parent = this.content.parent; const newHeight = parent.getMeasuredHeight(); if (newHeight === this.lastHeight) { return; } const { y } = parent.getLocationOnScreen(); this.startPositionY = Screen.mainScreen.heightDIPs - y - (this.showWhenKeyboardHidden === true ? newHeight : 0) / Screen.mainScreen.scale; this.log('_layout, startPositionY: ' + this.startPositionY); if (this.lastHeight === undefined) { // this moves the keyboardview to the bottom (just move it offscreen/toggle visibility(?) if the user doesn't want to show it without the keyboard being up) if (this.showWhenKeyboardHidden === true) { if (this.showAtBottomWhenKeyboardHidden === true) { parent.translateY = this.startPositionY; } } else { parent.translateY = this.startPositionY; } } else if (this.lastHeight !== newHeight) { parent.translateY = this.startPositionY; } this.lastHeight = newHeight; } } //# sourceMappingURL=index.ios.js.map