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);
}
}