mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
fix-next: handle action bar safe area nesting (#6455)
This commit is contained in:
@ -35,6 +35,7 @@ export function pageLoaded(args: EventData) {
|
|||||||
examples.set("webview", "web-view/main-page");
|
examples.set("webview", "web-view/main-page");
|
||||||
examples.set("progress-bar", "progress-bar/main-page");
|
examples.set("progress-bar", "progress-bar/main-page");
|
||||||
examples.set("date-picker", "date-picker/date-picker");
|
examples.set("date-picker", "date-picker/date-picker");
|
||||||
|
examples.set("nested-frames", "nested-frames/main-page");
|
||||||
page.bindingContext = new MainPageViewModel(wrapLayout, examples);
|
page.bindingContext = new MainPageViewModel(wrapLayout, examples);
|
||||||
|
|
||||||
const parent = page.getViewById("parentLayout");
|
const parent = page.getViewById("parentLayout");
|
||||||
|
10
apps/app/ui-tests-app/nested-frames/full-screen-n-n.xml
Normal file
10
apps/app/ui-tests-app/nested-frames/full-screen-n-n.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" actionBarHidden="true">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout backgroundColor="blue">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="never"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
10
apps/app/ui-tests-app/nested-frames/full-screen-n-y.xml
Normal file
10
apps/app/ui-tests-app/nested-frames/full-screen-n-y.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" actionBarHidden="true">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout backgroundColor="blue">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="always"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
10
apps/app/ui-tests-app/nested-frames/full-screen-y-n.xml
Normal file
10
apps/app/ui-tests-app/nested-frames/full-screen-y-n.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout backgroundColor="blue">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="never"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
10
apps/app/ui-tests-app/nested-frames/full-screen-y-y.xml
Normal file
10
apps/app/ui-tests-app/nested-frames/full-screen-y-y.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout backgroundColor="blue">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="always"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
28
apps/app/ui-tests-app/nested-frames/main-page.ts
Normal file
28
apps/app/ui-tests-app/nested-frames/main-page.ts
Normal file
@ -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 = <Page>args.object;
|
||||||
|
const wrapLayout = <WrapLayout>page.getViewById("wrapLayoutWithExamples");
|
||||||
|
page.bindingContext = new SubMainPageViewModel(wrapLayout, loadExamples());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadExamples() {
|
||||||
|
const examples = new Map<string, string>();
|
||||||
|
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;
|
||||||
|
}
|
6
apps/app/ui-tests-app/nested-frames/main-page.xml
Normal file
6
apps/app/ui-tests-app/nested-frames/main-page.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Page loaded="pageLoaded">
|
||||||
|
<ScrollView orientation="vertical" row="1">
|
||||||
|
<WrapLayout id="wrapLayoutWithExamples"/>
|
||||||
|
</ScrollView>
|
||||||
|
</Page>
|
12
apps/app/ui-tests-app/nested-frames/mid-screen-n-n.xml
Normal file
12
apps/app/ui-tests-app/nested-frames/mid-screen-n-n.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" actionBarHidden="true">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout rows="200, *" backgroundColor="blue">
|
||||||
|
<GridLayout row="1">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="never"></Frame>
|
||||||
|
</GridLayout>>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
12
apps/app/ui-tests-app/nested-frames/mid-screen-n-y.xml
Normal file
12
apps/app/ui-tests-app/nested-frames/mid-screen-n-y.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" actionBarHidden="true">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout rows="200, *" backgroundColor="blue">
|
||||||
|
<GridLayout row="1">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="always"></Frame>
|
||||||
|
</GridLayout>>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
12
apps/app/ui-tests-app/nested-frames/mid-screen-y-n.xml
Normal file
12
apps/app/ui-tests-app/nested-frames/mid-screen-y-n.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout rows="200, *" backgroundColor="blue">
|
||||||
|
<GridLayout row="1">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="never"></Frame>
|
||||||
|
</GridLayout>>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
12
apps/app/ui-tests-app/nested-frames/mid-screen-y-y.xml
Normal file
12
apps/app/ui-tests-app/nested-frames/mid-screen-y-y.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout rows="200, *" backgroundColor="blue">
|
||||||
|
<GridLayout row="1">
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="always"></Frame>
|
||||||
|
</GridLayout>>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
13
apps/app/ui-tests-app/nested-frames/nested-page.xml
Normal file
13
apps/app/ui-tests-app/nested-frames/nested-page.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Nested page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<GridLayout rows="*, *" columns="*, *" backgroundColor="red">
|
||||||
|
<Label row="0" col="0" text="test" backgroundColor="gold"></Label>
|
||||||
|
<Label row="0" col="1" text="test" backgroundColor="green"></Label>
|
||||||
|
<Label row="1" col="0" text="test" backgroundColor="yellow"></Label>
|
||||||
|
<Label row="1" col="1" text="test" backgroundColor="purple"></Label>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
14
apps/app/ui-tests-app/nested-frames/tab-n-n.xml
Normal file
14
apps/app/ui-tests-app/nested-frames/tab-n-n.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" actionBarHidden="true">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<TabView selectedTabTextColor="green">
|
||||||
|
<TabViewItem title="First">
|
||||||
|
<GridLayout>
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="never"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</TabViewItem>
|
||||||
|
</TabView>
|
||||||
|
</Page>
|
14
apps/app/ui-tests-app/nested-frames/tab-n-y.xml
Normal file
14
apps/app/ui-tests-app/nested-frames/tab-n-y.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" actionBarHidden="true">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<TabView selectedTabTextColor="green">
|
||||||
|
<TabViewItem title="First">
|
||||||
|
<GridLayout>
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="always"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</TabViewItem>
|
||||||
|
</TabView>
|
||||||
|
</Page>
|
14
apps/app/ui-tests-app/nested-frames/tab-y-n.xml
Normal file
14
apps/app/ui-tests-app/nested-frames/tab-y-n.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<TabView selectedTabTextColor="green">
|
||||||
|
<TabViewItem title="First">
|
||||||
|
<GridLayout>
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="never"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</TabViewItem>
|
||||||
|
</TabView>
|
||||||
|
</Page>
|
14
apps/app/ui-tests-app/nested-frames/tab-y-y.xml
Normal file
14
apps/app/ui-tests-app/nested-frames/tab-y-y.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd">
|
||||||
|
|
||||||
|
<ActionBar>
|
||||||
|
<Label text="Parent page"></Label>
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<TabView selectedTabTextColor="green">
|
||||||
|
<TabViewItem title="First">
|
||||||
|
<GridLayout>
|
||||||
|
<Frame id="nestedFrame" defaultPage="ui-tests-app/nested-frames/nested-page" actionBarVisibility="always"></Frame>
|
||||||
|
</GridLayout>
|
||||||
|
</TabViewItem>
|
||||||
|
</TabView>
|
||||||
|
</Page>
|
@ -704,21 +704,6 @@ export namespace ios {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function layoutView(controller: UIViewController, owner: View): void {
|
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;
|
let layoutGuide = controller.view.safeAreaLayoutGuide;
|
||||||
if (!layoutGuide) {
|
if (!layoutGuide) {
|
||||||
traceWrite(`safeAreaLayoutGuide during layout of ${owner}. Creating fallback constraints, but layout might be wrong.`,
|
traceWrite(`safeAreaLayoutGuide during layout of ${owner}. Creating fallback constraints, but layout might be wrong.`,
|
||||||
@ -897,6 +882,29 @@ export namespace ios {
|
|||||||
super.viewDidLayoutSubviews();
|
super.viewDidLayoutSubviews();
|
||||||
const owner = this.owner.get();
|
const owner = this.owner.get();
|
||||||
if (owner) {
|
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);
|
layoutView(this, owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,7 +602,7 @@ class iOSFrame implements iOSFrameDefinition {
|
|||||||
}
|
}
|
||||||
public set showNavigationBar(value: boolean) {
|
public set showNavigationBar(value: boolean) {
|
||||||
this._showNavigationBar = value;
|
this._showNavigationBar = value;
|
||||||
this._controller.setNavigationBarHiddenAnimated(!value, true);
|
this._controller.setNavigationBarHiddenAnimated(!value, !this._disableNavBarAnimation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get navBarVisibility(): "auto" | "never" | "always" {
|
public get navBarVisibility(): "auto" | "never" | "always" {
|
||||||
|
@ -217,6 +217,30 @@ class UIViewControllerImpl extends UIViewController {
|
|||||||
if (owner) {
|
if (owner) {
|
||||||
// layout(owner.actionBar)
|
// layout(owner.actionBar)
|
||||||
// layout(owner.content)
|
// 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);
|
iosView.layoutView(this, owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user