fix-next: handle action bar safe area nesting (#6455)

This commit is contained in:
Martin Yankov
2018-10-26 14:05:14 +03:00
committed by Svetoslav
parent 4765dd9302
commit e48782511d
19 changed files with 240 additions and 16 deletions

View File

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

View File

@@ -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" {

View File

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