From e48782511daa25ce1ce05157e65bc2dcfa1f79e0 Mon Sep 17 00:00:00 2001 From: Martin Yankov Date: Fri, 26 Oct 2018 14:05:14 +0300 Subject: [PATCH] fix-next: handle action bar safe area nesting (#6455) --- apps/app/ui-tests-app/main-page.ts | 1 + .../nested-frames/full-screen-n-n.xml | 10 +++++ .../nested-frames/full-screen-n-y.xml | 10 +++++ .../nested-frames/full-screen-y-n.xml | 10 +++++ .../nested-frames/full-screen-y-y.xml | 10 +++++ .../ui-tests-app/nested-frames/main-page.ts | 28 ++++++++++++++ .../ui-tests-app/nested-frames/main-page.xml | 6 +++ .../nested-frames/mid-screen-n-n.xml | 12 ++++++ .../nested-frames/mid-screen-n-y.xml | 12 ++++++ .../nested-frames/mid-screen-y-n.xml | 12 ++++++ .../nested-frames/mid-screen-y-y.xml | 12 ++++++ .../nested-frames/nested-page.xml | 13 +++++++ .../ui-tests-app/nested-frames/tab-n-n.xml | 14 +++++++ .../ui-tests-app/nested-frames/tab-n-y.xml | 14 +++++++ .../ui-tests-app/nested-frames/tab-y-n.xml | 14 +++++++ .../ui-tests-app/nested-frames/tab-y-y.xml | 14 +++++++ tns-core-modules/ui/core/view/view.ios.ts | 38 +++++++++++-------- tns-core-modules/ui/frame/frame.ios.ts | 2 +- tns-core-modules/ui/page/page.ios.ts | 24 ++++++++++++ 19 files changed, 240 insertions(+), 16 deletions(-) create mode 100644 apps/app/ui-tests-app/nested-frames/full-screen-n-n.xml create mode 100644 apps/app/ui-tests-app/nested-frames/full-screen-n-y.xml create mode 100644 apps/app/ui-tests-app/nested-frames/full-screen-y-n.xml create mode 100644 apps/app/ui-tests-app/nested-frames/full-screen-y-y.xml create mode 100644 apps/app/ui-tests-app/nested-frames/main-page.ts create mode 100644 apps/app/ui-tests-app/nested-frames/main-page.xml create mode 100644 apps/app/ui-tests-app/nested-frames/mid-screen-n-n.xml create mode 100644 apps/app/ui-tests-app/nested-frames/mid-screen-n-y.xml create mode 100644 apps/app/ui-tests-app/nested-frames/mid-screen-y-n.xml create mode 100644 apps/app/ui-tests-app/nested-frames/mid-screen-y-y.xml create mode 100644 apps/app/ui-tests-app/nested-frames/nested-page.xml create mode 100644 apps/app/ui-tests-app/nested-frames/tab-n-n.xml create mode 100644 apps/app/ui-tests-app/nested-frames/tab-n-y.xml create mode 100644 apps/app/ui-tests-app/nested-frames/tab-y-n.xml create mode 100644 apps/app/ui-tests-app/nested-frames/tab-y-y.xml diff --git a/apps/app/ui-tests-app/main-page.ts b/apps/app/ui-tests-app/main-page.ts index 027c174e3..1fd62f2a5 100644 --- a/apps/app/ui-tests-app/main-page.ts +++ b/apps/app/ui-tests-app/main-page.ts @@ -35,6 +35,7 @@ export function pageLoaded(args: EventData) { examples.set("webview", "web-view/main-page"); examples.set("progress-bar", "progress-bar/main-page"); examples.set("date-picker", "date-picker/date-picker"); + examples.set("nested-frames", "nested-frames/main-page"); page.bindingContext = new MainPageViewModel(wrapLayout, examples); const parent = page.getViewById("parentLayout"); diff --git a/apps/app/ui-tests-app/nested-frames/full-screen-n-n.xml b/apps/app/ui-tests-app/nested-frames/full-screen-n-n.xml new file mode 100644 index 000000000..3260e8f93 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/full-screen-n-n.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/full-screen-n-y.xml b/apps/app/ui-tests-app/nested-frames/full-screen-n-y.xml new file mode 100644 index 000000000..87b5d0c06 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/full-screen-n-y.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/full-screen-y-n.xml b/apps/app/ui-tests-app/nested-frames/full-screen-y-n.xml new file mode 100644 index 000000000..071ac75f0 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/full-screen-y-n.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/full-screen-y-y.xml b/apps/app/ui-tests-app/nested-frames/full-screen-y-y.xml new file mode 100644 index 000000000..fd53bf93c --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/full-screen-y-y.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/main-page.ts b/apps/app/ui-tests-app/nested-frames/main-page.ts new file mode 100644 index 000000000..1c01b725c --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/main-page.ts @@ -0,0 +1,28 @@ +import { EventData } from "tns-core-modules/data/observable"; +import { SubMainPageViewModel } from "../sub-main-page-view-model"; +import { WrapLayout } from "tns-core-modules/ui/layouts/wrap-layout"; +import { Page } from "tns-core-modules/ui/page"; + +export function pageLoaded(args: EventData) { + const page = args.object; + const wrapLayout = page.getViewById("wrapLayoutWithExamples"); + page.bindingContext = new SubMainPageViewModel(wrapLayout, loadExamples()); +} + +export function loadExamples() { + const examples = new Map(); + examples.set("full-screen-n-n", "nested-frames/full-screen-n-n"); + examples.set("full-screen-n-y", "nested-frames/full-screen-n-y"); + examples.set("full-screen-y-n", "nested-frames/full-screen-y-n"); + examples.set("full-screen-y-y", "nested-frames/full-screen-y-y"); + examples.set("mid-screen-n-n", "nested-frames/mid-screen-n-n"); + examples.set("mid-screen-n-y", "nested-frames/mid-screen-n-y"); + examples.set("mid-screen-y-n", "nested-frames/mid-screen-y-n"); + examples.set("mid-screen-y-y", "nested-frames/mid-screen-y-y"); + examples.set("tab-y-y", "nested-frames/tab-y-y"); + examples.set("tab-n-y", "nested-frames/tab-n-y"); + examples.set("tab-y-n", "nested-frames/tab-y-n"); + examples.set("tab-n-n", "nested-frames/tab-n-n"); + + return examples; +} \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/main-page.xml b/apps/app/ui-tests-app/nested-frames/main-page.xml new file mode 100644 index 000000000..33306f0d0 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/main-page.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/mid-screen-n-n.xml b/apps/app/ui-tests-app/nested-frames/mid-screen-n-n.xml new file mode 100644 index 000000000..4f9548a0f --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/mid-screen-n-n.xml @@ -0,0 +1,12 @@ + + + + + + + + + + > + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/mid-screen-n-y.xml b/apps/app/ui-tests-app/nested-frames/mid-screen-n-y.xml new file mode 100644 index 000000000..83d94d5e2 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/mid-screen-n-y.xml @@ -0,0 +1,12 @@ + + + + + + + + + + > + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/mid-screen-y-n.xml b/apps/app/ui-tests-app/nested-frames/mid-screen-y-n.xml new file mode 100644 index 000000000..09a123533 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/mid-screen-y-n.xml @@ -0,0 +1,12 @@ + + + + + + + + + + > + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/mid-screen-y-y.xml b/apps/app/ui-tests-app/nested-frames/mid-screen-y-y.xml new file mode 100644 index 000000000..80d59b599 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/mid-screen-y-y.xml @@ -0,0 +1,12 @@ + + + + + + + + + + > + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/nested-page.xml b/apps/app/ui-tests-app/nested-frames/nested-page.xml new file mode 100644 index 000000000..baa973660 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/nested-page.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/tab-n-n.xml b/apps/app/ui-tests-app/nested-frames/tab-n-n.xml new file mode 100644 index 000000000..4c90b270f --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/tab-n-n.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/tab-n-y.xml b/apps/app/ui-tests-app/nested-frames/tab-n-y.xml new file mode 100644 index 000000000..0f3b8096a --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/tab-n-y.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/tab-y-n.xml b/apps/app/ui-tests-app/nested-frames/tab-y-n.xml new file mode 100644 index 000000000..f9733fb12 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/tab-y-n.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/nested-frames/tab-y-y.xml b/apps/app/ui-tests-app/nested-frames/tab-y-y.xml new file mode 100644 index 000000000..2d06aab71 --- /dev/null +++ b/apps/app/ui-tests-app/nested-frames/tab-y-y.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tns-core-modules/ui/core/view/view.ios.ts b/tns-core-modules/ui/core/view/view.ios.ts index 13abd0766..0c1a5b15b 100644 --- a/tns-core-modules/ui/core/view/view.ios.ts +++ b/tns-core-modules/ui/core/view/view.ios.ts @@ -704,21 +704,6 @@ export namespace ios { } export function layoutView(controller: UIViewController, owner: View): void { - if (majorVersion >= 11) { - // apply parent page additional top insets if any. The scenario is when there is a parent page with action bar. - const parentPage = getAncestor(owner, "Page"); - if (parentPage) { - const parentPageInsetsTop = parentPage.viewController.view.safeAreaInsets.top; - const currentInsetsTop = controller.view.safeAreaInsets.top; - const additionalInsetsTop = parentPageInsetsTop - currentInsetsTop; - - if (additionalInsetsTop > 0) { - const additionalInsets = new UIEdgeInsets({ top: additionalInsetsTop, left: 0, bottom: 0, right: 0 }); - controller.additionalSafeAreaInsets = additionalInsets; - } - } - } - let layoutGuide = controller.view.safeAreaLayoutGuide; if (!layoutGuide) { traceWrite(`safeAreaLayoutGuide during layout of ${owner}. Creating fallback constraints, but layout might be wrong.`, @@ -897,6 +882,29 @@ export namespace ios { super.viewDidLayoutSubviews(); const owner = this.owner.get(); if (owner) { + if (majorVersion >= 11) { + // Handle nested UILayoutViewController safe area application. + // Currently, UILayoutViewController can be nested only in a TabView. + // The TabView itself is handled by the OS, so we check the TabView's parent (usually a Page, but can be a Layout). + const tabViewItem = owner.parent; + const tabView = tabViewItem && tabViewItem.parent; + const parent = tabView && tabView.parent; + if (parent) { + const parentPageInsetsTop = parent.nativeViewProtected.safeAreaInsets.top; + const currentInsetsTop = this.view.safeAreaInsets.top; + const additionalInsetsTop = Math.max(parentPageInsetsTop - currentInsetsTop, 0); + + const parentPageInsetsBottom = parent.nativeViewProtected.safeAreaInsets.bottom; + const currentInsetsBottom = this.view.safeAreaInsets.bottom; + const additionalInsetsBottom = Math.max(parentPageInsetsBottom - currentInsetsBottom, 0); + + if (additionalInsetsTop > 0 || additionalInsetsBottom > 0) { + const additionalInsets = new UIEdgeInsets({ top: additionalInsetsTop, left: 0, bottom: additionalInsetsBottom, right: 0 }); + this.additionalSafeAreaInsets = additionalInsets; + } + } + } + layoutView(this, owner); } } diff --git a/tns-core-modules/ui/frame/frame.ios.ts b/tns-core-modules/ui/frame/frame.ios.ts index 7b826c421..28ba4a2f6 100644 --- a/tns-core-modules/ui/frame/frame.ios.ts +++ b/tns-core-modules/ui/frame/frame.ios.ts @@ -602,7 +602,7 @@ class iOSFrame implements iOSFrameDefinition { } public set showNavigationBar(value: boolean) { this._showNavigationBar = value; - this._controller.setNavigationBarHiddenAnimated(!value, true); + this._controller.setNavigationBarHiddenAnimated(!value, !this._disableNavBarAnimation); } public get navBarVisibility(): "auto" | "never" | "always" { diff --git a/tns-core-modules/ui/page/page.ios.ts b/tns-core-modules/ui/page/page.ios.ts index 6d1e8f9c0..4e737ce36 100644 --- a/tns-core-modules/ui/page/page.ios.ts +++ b/tns-core-modules/ui/page/page.ios.ts @@ -217,6 +217,30 @@ class UIViewControllerImpl extends UIViewController { if (owner) { // layout(owner.actionBar) // layout(owner.content) + + if (majorVersion >= 11) { + // Handle nested Page safe area insets application. + // A Page is nested if its Frame has a parent. + // If the Page is nested, cross check safe area insets on top and bottom with Frame parent. + const frame = owner.parent; + // There is a legacy scenario where Page is not in a Frame - the root of a Modal View, so it has no parent. + const frameParent = frame && frame.parent; + if (frameParent) { + const parentPageInsetsTop = frameParent.nativeViewProtected.safeAreaInsets.top; + const currentInsetsTop = this.view.safeAreaInsets.top; + const additionalInsetsTop = Math.max(parentPageInsetsTop - currentInsetsTop, 0); + + const parentPageInsetsBottom = frameParent.nativeViewProtected.safeAreaInsets.bottom; + const currentInsetsBottom = this.view.safeAreaInsets.bottom; + const additionalInsetsBottom = Math.max(parentPageInsetsBottom - currentInsetsBottom, 0); + + if (additionalInsetsTop > 0 || additionalInsetsBottom > 0) { + const additionalInsets = new UIEdgeInsets({ top: additionalInsetsTop, left: 0, bottom: additionalInsetsBottom, right: 0 }); + this.additionalSafeAreaInsets = additionalInsets; + } + } + } + iosView.layoutView(this, owner); } }