UNPKG

@knotes/nativescript-keyboard-toolbar

Version:

NativeScript Keyboard Toolbar plugin

206 lines (205 loc) 9.01 kB
import { AnimationCurve } from "@nativescript/core/ui/enums"; import { Page } from "@nativescript/core/ui/page"; import { TabView } from "@nativescript/core/ui/tab-view"; import { ToolbarBase } from "./keyboard-toolbar.common"; import { Frame } from "@nativescript/core/ui/frame"; import { Application, Screen as screen, Utils } from '@nativescript/core'; export class Toolbar extends ToolbarBase { constructor() { super(); this.verticalAlignment = "top"; } _loaded() { setTimeout(() => this.applyInitialPosition(), 300); setTimeout(() => { const prepFocusEvents = (forView) => { forView.on("focus", () => { this.hasFocus = true; if (that.lastKeyboardHeight) { this.showToolbar(this.content.parent); } }); forView.on("blur", () => { this.hasFocus = false; this.hideToolbar(this.content.parent); }); }; let pg; if (Frame.topmost()) { pg = Frame.topmost().currentPage; } else { pg = this.content.parent; while (pg && !(pg instanceof Page)) { pg = pg.parent; } } this.thePage = pg; const forView = this.thePage.getViewById(this.forId); if (forView) { prepFocusEvents(forView); return; } let p = this.thePage.parent; while (p && !(p instanceof TabView)) { p = p.parent; } if (p instanceof TabView) { p.on(TabView.selectedIndexChangedEvent, () => { let forView2 = p.getViewById(this.forId); if (forView2) { prepFocusEvents(forView2); p.off(TabView.selectedIndexChangedEvent); } }); } else { console.log(`\n⌨ ⌨ ⌨ Please make sure forId="<view id>" resolves to a visible view, or the toolbar won't render correctly! Example: <Toolbar forId="${this.forId || "myId"}" height="44">\n\n`); } }, 500); const that = this; this.onGlobalLayoutListener = new android.view.ViewTreeObserver.OnGlobalLayoutListener({ onGlobalLayout() { if (!that.content.android) { return; } const rect = new android.graphics.Rect(); that.content.android.getWindowVisibleDisplayFrame(rect); const newKeyboardHeight = (Toolbar.getUsableScreenSizeY() - rect.bottom) / screen.mainScreen.scale; if (newKeyboardHeight <= 0 && that.lastKeyboardHeight === undefined) { return; } if (newKeyboardHeight === that.lastKeyboardHeight) { return; } that.lastKeyboardHeight = newKeyboardHeight; if (that.hasFocus) { if (newKeyboardHeight <= 0) { that.hideToolbar(that.content.parent); } else { that.showToolbar(that.content.parent); } } } }); that.content.android.getViewTreeObserver().addOnGlobalLayoutListener(that.onGlobalLayoutListener); } _unloaded() { this.content.android.getViewTreeObserver().removeOnGlobalLayoutListener(this.onGlobalLayoutListener); this.onGlobalLayoutListener = undefined; } showToolbar(parent) { let navbarHeight = this.isNavbarVisible ? 0 : this.navbarHeight; if (!this.isNavbarVisible) { const isNavbarVisibleWhenKeyboardOpen = this.thePage.getMeasuredHeight() < Toolbar.getUsableScreenSizeY() && (Toolbar.isVirtualNavbarHidden_butShowsWhenKeyboardIsOpen() || Toolbar.hasPermanentMenuKey()); if (isNavbarVisibleWhenKeyboardOpen) { if (!this.navbarHeightWhenKeyboardOpen) { this.navbarHeightWhenKeyboardOpen = Toolbar.getNavbarHeightWhenKeyboardOpen(); } navbarHeight = this.navbarHeightWhenKeyboardOpen; } } const animateToY = this.startPositionY - this.lastKeyboardHeight - (this.showWhenKeyboardHidden === true ? 0 : (this.lastHeight / screen.mainScreen.scale)) - navbarHeight; parent.animate({ translate: { x: 0, y: animateToY }, curve: AnimationCurve.cubicBezier(.32, .49, .56, 1), duration: 370 }).then(() => { }); } hideToolbar(parent) { const animateToY = this.showWhenKeyboardHidden === true && this.showAtBottomWhenKeyboardHidden !== true ? 0 : (this.startPositionY + this.navbarHeight); parent.animate({ translate: { x: 0, y: animateToY }, curve: AnimationCurve.cubicBezier(.32, .49, .56, 1), duration: 370 }).then(() => { }); } applyInitialPosition() { if (this.startPositionY !== undefined) { return; } const parent = this.content.parent; this.thePage = parent; while (!this.thePage && !this.thePage.frame) { this.thePage = this.thePage.parent; } const loc = parent.getLocationOnScreen(); if (!loc) { return; } const y = loc.y; const newHeight = parent.getMeasuredHeight(); this.navbarHeight = Toolbar.getNavbarHeight(); this.isNavbarVisible = !!this.navbarHeight; this.startPositionY = screen.mainScreen.heightDIPs - y - ((this.showWhenKeyboardHidden === true ? newHeight : 0) / screen.mainScreen.scale) - (this.isNavbarVisible ? this.navbarHeight : 0); if (this.lastHeight === undefined) { if (this.showWhenKeyboardHidden === true) { if (this.showAtBottomWhenKeyboardHidden === true) { parent.translateY = this.startPositionY; } } else { parent.translateY = this.startPositionY + this.navbarHeight; } } else if (this.lastHeight !== newHeight) { parent.translateY = this.startPositionY + this.navbarHeight; } this.lastHeight = newHeight; } static getNavbarHeight() { const context = Utils.ad.getApplicationContext(); let navBarHeight = 0; let windowManager = context.getSystemService(android.content.Context.WINDOW_SERVICE); let d = windowManager.getDefaultDisplay(); let realDisplayMetrics = new android.util.DisplayMetrics(); d.getRealMetrics(realDisplayMetrics); let realHeight = realDisplayMetrics.heightPixels; let realWidth = realDisplayMetrics.widthPixels; let displayMetrics = new android.util.DisplayMetrics(); d.getMetrics(displayMetrics); let displayHeight = displayMetrics.heightPixels; let displayWidth = displayMetrics.widthPixels; if ((realHeight - displayHeight) > 0) { navBarHeight = realHeight - displayHeight; } else if ((realWidth - displayWidth) > 0) { navBarHeight = realWidth - displayWidth; } return navBarHeight / context.getResources().getDisplayMetrics().density; } static getNavbarHeightWhenKeyboardOpen() { const resources = Utils.ad.getApplicationContext().getResources(); const resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId) / screen.mainScreen.scale; } return 0; } static hasPermanentMenuKey() { return android.view.ViewConfiguration.get(Utils.ad.getApplicationContext()).hasPermanentMenuKey(); } static isVirtualNavbarHidden_butShowsWhenKeyboardIsOpen() { if (Toolbar.supportVirtualKeyboardCheck !== undefined) { return Toolbar.supportVirtualKeyboardCheck; } const SAMSUNG_NAVIGATION_EVENT = "navigationbar_hide_bar_enabled"; try { Toolbar.supportVirtualKeyboardCheck = android.provider.Settings.Global.getInt(Application.android.foregroundActivity.getContentResolver(), SAMSUNG_NAVIGATION_EVENT) === 1; } catch (e) { console.log(">> e: " + e); Toolbar.supportVirtualKeyboardCheck = false; } return Toolbar.supportVirtualKeyboardCheck; } static getUsableScreenSizeY() { const screenSize = new android.graphics.Point(); Application.android.foregroundActivity.getWindowManager().getDefaultDisplay().getSize(screenSize); return screenSize.y; } }