@knotes/nativescript-keyboard-toolbar
Version:
NativeScript Keyboard Toolbar plugin
206 lines (205 loc) • 9.01 kB
JavaScript
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;
}
}