feat(ios): enable safe area for stack and grid

This commit is contained in:
Martin Yankov
2018-06-13 11:40:42 +03:00
parent 71107533bb
commit d4ec355466
6 changed files with 176 additions and 38 deletions

View File

@@ -641,7 +641,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
}
public abstract onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void;
public abstract onLayout(left: number, top: number, right: number, bottom: number): void;
public abstract onLayout(left: number, top: number, right: number, bottom: number, insetLeft?: number, insetTop?: number): void;
public abstract layoutNativeView(left: number, top: number, right: number, bottom: number): void;
public static resolveSizeAndState(size: number, specSize: number, specMode: number, childMeasuredState: number): number {
@@ -879,6 +879,14 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
return undefined;
}
public getFullscreenArea(): any {
return undefined;
}
public getSafeArea(): any {
return undefined;
}
public getLocationInWindow(): Point {
return undefined;
}

View File

@@ -404,7 +404,7 @@ export abstract class View extends ViewBase {
* @param right Right position, relative to parent
* @param bottom Bottom position, relative to parent
*/
public onLayout(left: number, top: number, right: number, bottom: number): void;
public onLayout(left: number, top: number, right: number, bottom: number, insetLeft?: number, insetTop?: number): void;
/**
* This method must be called by onMeasure(int, int) to store the measured width and measured height. Failing to do so will trigger an exception at measurement time.
@@ -527,6 +527,16 @@ export abstract class View extends ViewBase {
*/
public createAnimation(options: AnimationDefinition): Animation;
/**
* Returns the iOS safe area frame of the closest parent with UIViewController.
*/
public getSafeArea(): any;
/**
* Returns the iOS frame of the closest parent with UIViewController.
*/
public getFullscreenArea(): any;
/**
* Returns the location of this view in the window coordinate system.
*/
@@ -609,7 +619,7 @@ export abstract class View extends ViewBase {
* Called by layout method to cache view bounds.
* @private
*/
_setCurrentLayoutBounds(left: number, top: number, right: number, bottom: number): void;
_setCurrentLayoutBounds(left: number, top: number, right: number, bottom: number): { boundsChanged: boolean, sizeChanged: boolean };
/**
* Return view bounds.
* @private

View File

@@ -90,7 +90,15 @@ export class View extends ViewCommon {
}
if (boundsChanged || (this._privateFlags & PFLAG_LAYOUT_REQUIRED) === PFLAG_LAYOUT_REQUIRED) {
this.onLayout(left, top, right, bottom);
let insetLeft = 0;
let insetTop = 0;
if (this.nativeViewProtected.safeAreaInsets) {
insetLeft = layout.toDevicePixels(this.nativeViewProtected.safeAreaInsets.left);
insetTop = layout.toDevicePixels(this.nativeViewProtected.safeAreaInsets.top);
}
this.onLayout(left, top, right, bottom, insetLeft, insetTop);
this._privateFlags &= ~PFLAG_LAYOUT_REQUIRED;
}
@@ -138,7 +146,7 @@ export class View extends ViewCommon {
this.setMeasuredDimension(widthAndState, heightAndState);
}
public onLayout(left: number, top: number, right: number, bottom: number): void {
public onLayout(left: number, top: number, right: number, bottom: number, insetLeft?: number, insetTop?: number): void {
//
}
@@ -159,8 +167,30 @@ export class View extends ViewCommon {
nativeView.frame = frame;
}
const boundsOrigin = nativeView.bounds.origin;
nativeView.bounds = CGRectMake(boundsOrigin.x, boundsOrigin.y, frame.size.width, frame.size.height);
if (nativeView.safeAreaInsets) {
const leftInset = layout.toDevicePixels(nativeView.safeAreaInsets.left);
const topInset = layout.toDevicePixels(nativeView.safeAreaInsets.top);
const left = layout.toDevicePixels(frame.origin.x);
const top = layout.toDevicePixels(frame.origin.y);
const right = layout.toDevicePixels(frame.origin.x + frame.size.width);
const bottom = layout.toDevicePixels(frame.origin.y + frame.size.height);
if (leftInset || topInset) {
const frameNew = CGRectMake(layout.toDeviceIndependentPixels(left + leftInset), layout.toDeviceIndependentPixels(top + topInset), layout.toDeviceIndependentPixels(right - left), layout.toDeviceIndependentPixels(bottom - top));
nativeView.frame = frameNew;
const boundsOrigin = nativeView.bounds.origin;
nativeView.bounds = CGRectMake(boundsOrigin.x, boundsOrigin.y, frameNew.size.width, frameNew.size.height);
}
else {
const boundsOrigin = nativeView.bounds.origin;
nativeView.bounds = CGRectMake(boundsOrigin.x, boundsOrigin.y, frame.size.width, frame.size.height);
}
}
else {
const boundsOrigin = nativeView.bounds.origin;
nativeView.bounds = CGRectMake(boundsOrigin.x, boundsOrigin.y, frame.size.width, frame.size.height);
}
this._raiseLayoutChangedEvent();
this._isLaidOut = true;
} else if (!this._isLaidOut) {
@@ -203,6 +233,16 @@ export class View extends ViewCommon {
return false;
}
public getFullscreenArea(): any {
const parentWithController = ios.getParentWithViewController(this);
return parentWithController.viewController.view.frame;
}
public getSafeArea(): any {
const parentWithController = ios.getParentWithViewController(this);
return parentWithController.viewController.view.safeAreaLayoutGuide.layoutFrame;
}
public getLocationInWindow(): Point {
if (!this.nativeViewProtected || !this.nativeViewProtected.window) {
return undefined;
@@ -688,34 +728,44 @@ export namespace ios {
fullscreenSize.height -= (statusBarHeight + navBarHeight);
}
left = safeOrigin.x;
width = safeAreaSize.width;
// left = safeOrigin.x;
// width = safeAreaSize.width;
// top = safeOrigin.y;
// height = safeAreaSize.height;
if (hasChildControllers) {
// If not inner most extend to fullscreen
top = fullscreenOrigin.y;
height = fullscreenSize.height;
} else if (!scrollable) {
// If not scrollable dock under safe area
top = safeOrigin.y;
height = safeAreaSize.height;
} else if (navBarHidden) {
// If scrollable but no navigation bar dock under safe area
top = safeOrigin.y;
height = navController ? (fullscreenSize.height - top) : safeAreaSize.height;
} else {
// If scrollable and navigation bar extend to fullscreen
top = fullscreenOrigin.y;
height = fullscreenSize.height;
}
left = fullscreenOrigin.x;
width = fullscreenSize.width;
top = fullscreenOrigin.y;
height = fullscreenSize.height;
// if (hasChildControllers) {
// // If not inner most extend to fullscreen
// top = fullscreenOrigin.y;
// height = fullscreenSize.height;
// } else if (!scrollable) {
// // If not scrollable dock under safe area
// top = safeOrigin.y;
// height = safeAreaSize.height;
// } else if (navBarHidden) {
// // If scrollable but no navigation bar dock under safe area
// top = safeOrigin.y;
// height = navController ? (fullscreenSize.height - top) : safeAreaSize.height;
// } else {
// // If scrollable and navigation bar extend to fullscreen
// top = fullscreenOrigin.y;
// height = fullscreenSize.height;
// }
left = layout.toDevicePixels(left);
top = layout.toDevicePixels(top);
width = layout.toDevicePixels(width);
height = layout.toDevicePixels(height);
const widthSpec = layout.makeMeasureSpec(width, layout.EXACTLY);
const heightSpec = layout.makeMeasureSpec(height, layout.EXACTLY);
const safeAreaWidth = layout.toDevicePixels(safeAreaSize.width);
const safeAreaHeight = layout.toDevicePixels(safeAreaSize.height);
const widthSpec = layout.makeMeasureSpec(safeAreaWidth, layout.EXACTLY);
const heightSpec = layout.makeMeasureSpec(safeAreaHeight, layout.EXACTLY);
View.measureChild(null, owner, widthSpec, heightSpec);
View.layoutChild(null, owner, left, top, width + left, height + top);