refactor safe area application code

This commit is contained in:
Martin Yankov
2018-08-09 15:28:34 +03:00
parent 1858cba4ed
commit 8df5fbd7a8
11 changed files with 175 additions and 393 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, insets?: {left, top, right, bottom}): void;
public abstract onLayout(left: number, top: number, right: number, bottom: 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,18 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
return undefined;
}
public getSafeAreaInsets(): { left, top, right, bottom } {
return undefined;
}
public getPositionFromFrame(frame: CGRect): { left, top, right, bottom } {
return undefined;
}
public getFrameFromPosition(position: { left, top, right, bottom }, insets?: { left, top }): CGRect {
return undefined;
}
public getFullscreenArea(): any {
return undefined;
}

View File

@@ -816,7 +816,11 @@ export class View extends ViewCommon {
}
}
export class CustomLayoutView extends View implements CustomLayoutViewDefinition {
export class ContainerView extends View {
//
}
export class CustomLayoutView extends ContainerView implements CustomLayoutViewDefinition {
nativeViewProtected: android.view.ViewGroup;
public createNativeView() {

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, insets?: {left, top, right, bottom}): void;
public onLayout(left: number, top: number, right: number, bottom: 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.
@@ -415,7 +415,6 @@ export abstract class View extends ViewBase {
/**
* Called from onLayout when native view position is about to be changed.
* @param parent This parameter is not used. You can pass null.
* @param left Left position, relative to parent
* @param top Top position, relative to parent
* @param right Right position, relative to parent
@@ -427,7 +426,7 @@ export abstract class View extends ViewBase {
* Measure a child by taking into account its margins and a given measureSpecs.
* @param parent This parameter is not used. You can pass null.
* @param child The view to be measured.
* @param measuredWidth The measured width that the parent layout specifies for this view.
* @param measuredWidth The measured width that the parent layout specifies for this view.
* @param measuredHeight The measured height that the parent layout specifies for this view.
*/
public static measureChild(parent: View, child: View, widthMeasureSpec: number, heightMeasureSpec: number): { measuredWidth: number; measuredHeight: number };
@@ -527,6 +526,21 @@ export abstract class View extends ViewBase {
*/
public createAnimation(options: AnimationDefinition): Animation;
/**
* Returns the iOS safe area insets of this view.
*/
public getSafeAreaInsets(): { left, top, right, bottom };
/**
* Transforms iOS CGRect to a position object with left, top, right and bottom.
*/
public getPositionFromFrame(frame: any): { left, top, right, bottom };
/**
* Transforms a position object with left, top, right and bottom to an iOS CGRect.
*/
public getFrameFromPosition(position: { left, top, right, bottom }, insets?: { left, top }): any;
/**
* Returns the iOS safe area frame of the closest parent with UIViewController.
*/
@@ -710,10 +724,17 @@ export abstract class View extends ViewBase {
_setValue(property: any, value: any): never;
}
/**
* Base class for all UI components that are containers.
*/
export class ContainerView extends View {
}
/**
* Base class for all UI components that implement custom layouts.
*/
export class CustomLayoutView extends View {
export class CustomLayoutView extends ContainerView {
//@private
/**
* @private

View File

@@ -87,22 +87,18 @@ export class View extends ViewCommon {
@profile
public layout(left: number, top: number, right: number, bottom: number, setFrame = true): void {
const { boundsChanged, sizeChanged } = this._setCurrentLayoutBounds(left, top, right, bottom);
let actualPosition = {left, top, right, bottom};
if (setFrame) {
actualPosition = this.layoutNativeView(left, top, right, bottom) || actualPosition;
this.layoutNativeView(left, top, right, bottom);
}
if (boundsChanged || (this._privateFlags & PFLAG_LAYOUT_REQUIRED) === PFLAG_LAYOUT_REQUIRED) {
let insets = { left: 0, top: 0, right: 0, bottom: 0};
if (majorVersion > 10) {
insets.left = layout.toDevicePixels(this.nativeViewProtected.safeAreaInsets.left);
insets.top = layout.toDevicePixels(this.nativeViewProtected.safeAreaInsets.top);
insets.right = layout.toDevicePixels(this.nativeViewProtected.safeAreaInsets.right);
insets.bottom = layout.toDevicePixels(this.nativeViewProtected.safeAreaInsets.bottom);
let position = { left, top, right, bottom };
if (this.nativeViewProtected) {
const frame = this.nativeViewProtected.frame;
position = this.getPositionFromFrame(frame);
}
this.onLayout(actualPosition.left, actualPosition.top, actualPosition.right, actualPosition.bottom, insets);
this.onLayout(position.left, position.top, position.right, position.bottom);
this._privateFlags &= ~PFLAG_LAYOUT_REQUIRED;
}
@@ -150,11 +146,11 @@ export class View extends ViewCommon {
this.setMeasuredDimension(widthAndState, heightAndState);
}
public onLayout(left: number, top: number, right: number, bottom: number, insets?: {left, top, right, bottom}): void {
//
public onLayout(left: number, top: number, right: number, bottom: number): void {
//
}
public _setNativeViewFrame(nativeView: UIView, frame: CGRect): CGRect {
public _setNativeViewFrame(nativeView: UIView, frame: CGRect): void {
if (!CGRectEqualToRect(nativeView.frame, frame)) {
if (traceEnabled()) {
traceWrite(this + ", Native setFrame: = " + NSStringFromCGRect(frame), traceCategories.Layout);
@@ -166,34 +162,18 @@ export class View extends ViewCommon {
nativeView.transform = CGAffineTransformIdentity;
nativeView.frame = frame;
nativeView.transform = transform;
}
else {
} else {
nativeView.frame = frame;
}
if (nativeView.safeAreaInsets) {
const leftInset = layout.toDevicePixels(nativeView.safeAreaInsets.left);
const topInset = layout.toDevicePixels(nativeView.safeAreaInsets.top);
const adjustedFrame = this.applySafeAreaInsets(frame);
if (adjustedFrame) {
nativeView.frame = adjustedFrame;
}
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);
}
const boundsOrigin = nativeView.bounds.origin;
const boundsFrame = nativeView.frame;
nativeView.bounds = CGRectMake(boundsOrigin.x, boundsOrigin.y, boundsFrame.size.width, boundsFrame.size.height);
this._raiseLayoutChangedEvent();
this._isLaidOut = true;
@@ -201,25 +181,16 @@ export class View extends ViewCommon {
// Rects could be equal on the first layout and an event should be raised.
this._raiseLayoutChangedEvent();
}
return nativeView.frame;
}
public layoutNativeView(left: number, top: number, right: number, bottom: number): any {
public layoutNativeView(left: number, top: number, right: number, bottom: number): void {
if (!this.nativeViewProtected) {
return;
}
const nativeView = this.nativeViewProtected;
const frame = CGRectMake(layout.toDeviceIndependentPixels(left), layout.toDeviceIndependentPixels(top), layout.toDeviceIndependentPixels(right - left), layout.toDeviceIndependentPixels(bottom - top));
const actualFrame = this._setNativeViewFrame(nativeView, frame) || frame;
const actualLeft = Math.round(layout.toDevicePixels(actualFrame.origin.x));
const actualTop = Math.round(layout.toDevicePixels(actualFrame.origin.y));
const actualRight = Math.round(layout.toDevicePixels(actualFrame.origin.x + actualFrame.size.width));
const actualBottom = Math.round(layout.toDevicePixels(actualFrame.origin.y + actualFrame.size.height));
return { left: actualLeft, top: actualTop, right: actualRight, bottom: actualBottom};
const frame = this.getFrameFromPosition({ left, top, right, bottom });
this._setNativeViewFrame(nativeView, frame);
}
public _setLayoutFlags(left: number, top: number, right: number, bottom: number): void {
@@ -246,6 +217,54 @@ export class View extends ViewCommon {
return false;
}
protected applySafeAreaInsets(frame: CGRect): CGRect {
if (majorVersion > 10) {
const insets = this.getSafeAreaInsets();
if (insets.left || insets.top) {
const position = this.getPositionFromFrame(frame);
const adjustedFrame = this.getFrameFromPosition(position, insets);
return adjustedFrame;
}
}
return null;
}
public getSafeAreaInsets(): { left, top, right, bottom } {
const safeAreaInsets = this.nativeViewProtected && this.nativeViewProtected.safeAreaInsets;
let insets = { left: 0, top: 0, right: 0, bottom: 0 };
if (safeAreaInsets) {
insets.left = layout.round(layout.toDevicePixels(safeAreaInsets.left));
insets.top = layout.round(layout.toDevicePixels(safeAreaInsets.top));
insets.right = layout.round(layout.toDevicePixels(safeAreaInsets.right));
insets.bottom = layout.round(layout.toDevicePixels(safeAreaInsets.bottom));
}
return insets;
}
public getPositionFromFrame(frame: CGRect): { left, top, right, bottom } {
const left = layout.round(layout.toDevicePixels(frame.origin.x));
const top = layout.round(layout.toDevicePixels(frame.origin.y));
const right = layout.round(layout.toDevicePixels(frame.origin.x + frame.size.width));
const bottom = layout.round(layout.toDevicePixels(frame.origin.y + frame.size.height));
return { left, right, top, bottom };
}
public getFrameFromPosition(position: { left, top, right, bottom }, insets?: { left, top }): CGRect {
insets = insets || { left: 0, top: 0 };
const left = layout.round(layout.toDeviceIndependentPixels(position.left + insets.left));
const top = layout.round(layout.toDeviceIndependentPixels(position.top + insets.top));
const width = layout.round(layout.toDeviceIndependentPixels(position.right - position.left));
const height = layout.round(layout.toDeviceIndependentPixels(position.bottom - position.top));
return CGRectMake(left, top, width, height);
}
public getFullscreenArea(): any {
const parentWithController = ios.getParentWithViewController(this);
return parentWithController.viewController.view.frame;
@@ -419,7 +438,7 @@ export class View extends ViewCommon {
protected _hideNativeModalView(parent: View) {
if (!parent || !parent.viewController) {
traceError("Trying to hide modal view but no parent with viewController specified.")
return;
return;
}
const parentController = parent.viewController;
@@ -585,7 +604,49 @@ export class View extends ViewCommon {
}
View.prototype._nativeBackgroundState = "unset";
export class CustomLayoutView extends View {
export class ContainerView extends View {
protected applySafeAreaInsets(frame: CGRect): CGRect {
if (majorVersion > 10) {
const locationOnScreen = this.getLocationOnScreen();
if (locationOnScreen) {
const safeArea = this.getSafeArea();
const fullscreen = this.getFullscreenArea();
const onScreenLeft = layout.round(layout.toDevicePixels(locationOnScreen.x));
const onScreenTop = layout.round(layout.toDevicePixels(locationOnScreen.y));
const position = this.getPositionFromFrame(frame);
const safeAreaPosition = this.getPositionFromFrame(safeArea);
const fullscreenPosition = this.getPositionFromFrame(fullscreen);
const adjustedPosition = position;
if (position.left && onScreenLeft <= safeAreaPosition.left) {
adjustedPosition.left = fullscreenPosition.left;
}
if (position.top && onScreenTop <= safeAreaPosition.top) {
adjustedPosition.top = fullscreenPosition.top;
}
if (position.right < fullscreenPosition.right && position.right >= safeAreaPosition.right) {
adjustedPosition.right = fullscreenPosition.right;
}
if (position.bottom < fullscreenPosition.bottom && position.bottom >= safeAreaPosition.bottom) {
adjustedPosition.bottom = fullscreenPosition.bottom;
}
const adjustedFrame = CGRectMake(layout.toDeviceIndependentPixels(adjustedPosition.left), layout.toDeviceIndependentPixels(adjustedPosition.top), layout.toDeviceIndependentPixels(adjustedPosition.right - adjustedPosition.left), layout.toDeviceIndependentPixels(adjustedPosition.bottom - adjustedPosition.top));
return adjustedFrame;
}
}
return null;
}
}
export class CustomLayoutView extends ContainerView {
nativeViewProtected: UIView;
@@ -683,8 +744,7 @@ export namespace ios {
}
export function updateConstraints(controller: UIViewController, owner: View): void {
const root = controller.view;
if (!root.safeAreaLayoutGuide) {
if (majorVersion <= 10) {
const layoutGuide = initLayoutGuide(controller);
(<any>controller.view).safeAreaLayoutGuide = layoutGuide;
}
@@ -703,27 +763,7 @@ export namespace ios {
return layoutGuide;
}
function getStatusBarHeight(viewController?: UIViewController): number {
const app = iosUtils.getter(UIApplication, UIApplication.sharedApplication);
if (!app || app.statusBarHidden) {
return 0;
}
if (viewController && viewController.prefersStatusBarHidden) {
return 0;
}
const statusFrame = app.statusBarFrame;
return Math.min(statusFrame.size.width, statusFrame.size.height);
}
export function layoutView(controller: UIViewController, owner: View): void {
let left: number, top: number, width: number, height: number;
const frame = controller.view.frame;
const fullscreenOrigin = frame.origin;
const fullscreenSize = frame.size;
let layoutGuide = controller.view.safeAreaLayoutGuide;
if (!layoutGuide) {
traceWrite(`safeAreaLayoutGuide during layout of ${owner}. Creating fallback constraints, but layout might be wrong.`,
@@ -732,62 +772,17 @@ export namespace ios {
layoutGuide = initLayoutGuide(controller);
}
const safeArea = layoutGuide.layoutFrame;
const safeOrigin = safeArea.origin;
const position = owner.getPositionFromFrame(safeArea);
const safeAreaSize = safeArea.size;
const navController = controller.navigationController;
const navBarHidden = navController ? navController.navigationBarHidden : true;
const scrollable = isContentScrollable(controller, owner);
const hasChildControllers = controller.childViewControllers.count > 0;
if (!(controller.edgesForExtendedLayout & UIRectEdge.Top)) {
const statusBarHeight = getStatusBarHeight(controller);
const navBarHeight = controller.navigationController ? controller.navigationController.navigationBar.frame.size.height : 0;
fullscreenOrigin.y = safeOrigin.y;
fullscreenSize.height -= (statusBarHeight + navBarHeight);
}
left = safeOrigin.x;
width = safeAreaSize.width;
top = safeOrigin.y;
height = safeAreaSize.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 safeAreaWidth = layout.toDevicePixels(safeAreaSize.width);
const safeAreaHeight = layout.toDevicePixels(safeAreaSize.height);
const safeAreaWidth = layout.round(layout.toDevicePixels(safeAreaSize.width));
const safeAreaHeight = layout.round(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);
View.layoutChild(null, owner, position.left, position.top, position.right, position.bottom);
layoutParent(owner.parent);
}

View File

@@ -156,9 +156,11 @@ export class GridLayout extends GridLayoutBase {
this.setMeasuredDimension(widthSizeAndState, heightSizeAndState);
}
public onLayout(left: number, top: number, right: number, bottom: number, insets: {left, top, right, bottom}): void {
public onLayout(left: number, top: number, right: number, bottom: number): void {
super.onLayout(left, top, right, bottom);
const insets = this.getSafeAreaInsets();
let paddingLeft = this.effectiveBorderLeftWidth + this.effectivePaddingLeft + insets.left;
let paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;

View File

@@ -33,82 +33,6 @@ export class LayoutBase extends LayoutBaseCommon {
}
}
public _setNativeViewFrame(nativeView: UIView, frame: CGRect) {
// if (!CGRectEqualToRect(nativeView.frame, frame)) {
// if (traceEnabled()) {
// traceWrite(this + ", Native setFrame: = " + NSStringFromCGRect(frame), traceCategories.Layout);
// }
// this._cachedFrame = frame;
// if (this._hasTransfrom) {
// // Always set identity transform before setting frame;
// const transform = nativeView.transform;
// nativeView.transform = CGAffineTransformIdentity;
// nativeView.frame = frame;
// nativeView.transform = transform;
// }
// else {
// nativeView.frame = frame;
// }
nativeView.frame = frame;
const locationOnScreen = this.getLocationInWindow();
if (locationOnScreen) {
const safeArea = this.getSafeArea();
const fullscreen = this.getFullscreenArea();
const onScreenLeft = layout.toDevicePixels(layout.round(locationOnScreen.x));
const onScreenTop = layout.toDevicePixels(layout.round(locationOnScreen.y));
let left = layout.toDevicePixels(frame.origin.x);
let top = layout.toDevicePixels(frame.origin.y);
let width = layout.toDevicePixels(frame.size.width);
let height = layout.toDevicePixels(frame.size.height);
if (majorVersion > 10) {
let newLeft = left;
let newTop = top;
let newWidth = width;
let newHeight = height;
if (left !== 0 && onScreenLeft <= layout.toDevicePixels(safeArea.origin.x)) {
newLeft = layout.toDevicePixels(fullscreen.origin.x);
newWidth = width + onScreenLeft;
}
if (top !== 0 && onScreenTop <= layout.toDevicePixels(safeArea.origin.y)) {
newTop = layout.toDevicePixels(fullscreen.origin.y);
newHeight = height + onScreenTop;
}
if (width && width < layout.toDevicePixels(fullscreen.size.width) && onScreenLeft + width >= layout.toDevicePixels(safeArea.origin.x) + layout.toDevicePixels(safeArea.size.width)) {
newWidth = newWidth + (layout.toDevicePixels(fullscreen.size.width) - (onScreenLeft + width));
}
if (height && height < layout.toDevicePixels(fullscreen.size.height) && onScreenTop + height >= layout.toDevicePixels(safeArea.origin.y) + layout.toDevicePixels(safeArea.size.height)) {
newHeight = newHeight + (layout.toDevicePixels(fullscreen.size.height) - (onScreenTop + height));
}
const frameNew = CGRectMake(layout.toDeviceIndependentPixels(newLeft), layout.toDeviceIndependentPixels(newTop), layout.toDeviceIndependentPixels(newWidth), layout.toDeviceIndependentPixels(newHeight));
nativeView.frame = frameNew;
}
}
// if (leftInset || topInset) {
// const frameNew = CGRectMake(layout.toDeviceIndependentPixels(left), layout.toDeviceIndependentPixels(top), layout.toDeviceIndependentPixels(right - left + leftInset), layout.toDeviceIndependentPixels(bottom - top + topInset));
// 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, nativeView.frame.size.width, nativeView.frame.size.height);
// }
// }
return nativeView.frame;
}
[clipToBoundsProperty.getDefault](): boolean {
return false;
}

View File

@@ -81,8 +81,10 @@ export class StackLayout extends StackLayoutBase {
this.setMeasuredDimension(widthAndState, heightAndState);
}
public onLayout(left: number, top: number, right: number, bottom: number, insets: {left, top, right, bottom}): void {
public onLayout(left: number, top: number, right: number, bottom: number): void {
super.onLayout(left, top, right, bottom);
const insets = this.getSafeAreaInsets();
if (this.orientation === "vertical") {
this.layoutVertical(left, top, right, bottom, insets);
}
@@ -100,7 +102,6 @@ export class StackLayout extends StackLayoutBase {
let childTop: number;
let childLeft: number = paddingLeft;
let childRight = right - left - paddingRight;
// let childRight = right - paddingRight;
switch (this.verticalAlignment) {
case VerticalAlignment.MIDDLE:

View File

@@ -119,9 +119,10 @@ export class WrapLayout extends WrapLayoutBase {
this.setMeasuredDimension(widthAndState, heightAndState);
}
public onLayout(left: number, top: number, right: number, bottom: number, insets: { left, top, right, bottom }): void {
public onLayout(left: number, top: number, right: number, bottom: number): void {
super.onLayout(left, top, right, bottom);
const insets = this.getSafeAreaInsets();
const isVertical = this.orientation === "vertical";
const paddingLeft = this.effectiveBorderLeftWidth + this.effectivePaddingLeft + insets.left;
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;

View File

@@ -1,5 +1,5 @@
import { ListView as ListViewDefinition, ItemsSource, ItemEventData, TemplatedItemsView } from ".";
import { CoercibleProperty, CssProperty, Style, View, Template, KeyedTemplate, Length, Property, Color, Observable, EventData, CSSType } from "../core/view";
import { CoercibleProperty, CssProperty, Style, View, ViewBase, ContainerView, Template, KeyedTemplate, Length, Property, Color, Observable, EventData, CSSType } from "../core/view";
import { parse, parseMultipleTemplates } from "../builder";
import { Label } from "../label";
import { ObservableArray, ChangedData } from "../../data/observable-array";
@@ -19,7 +19,7 @@ export module knownMultiTemplates {
const autoEffectiveRowHeight = -1;
@CSSType("ListView")
export abstract class ListViewBase extends View implements ListViewDefinition, TemplatedItemsView {
export abstract class ListViewBase extends ContainerView implements ListViewDefinition, TemplatedItemsView {
public static itemLoadingEvent = "itemLoading";
public static itemTapEvent = "itemTap";
public static loadMoreItemsEvent = "loadMoreItems";

View File

@@ -380,81 +380,6 @@ export class ListView extends ListViewBase {
});
}
public _setNativeViewFrame(nativeView: UIView, frame: CGRect) {
// if (!CGRectEqualToRect(nativeView.frame, frame)) {
// if (traceEnabled()) {
// traceWrite(this + ", Native setFrame: = " + NSStringFromCGRect(frame), traceCategories.Layout);
// }
// this._cachedFrame = frame;
// if (this._hasTransfrom) {
// // Always set identity transform before setting frame;
// const transform = nativeView.transform;
// nativeView.transform = CGAffineTransformIdentity;
// nativeView.frame = frame;
// nativeView.transform = transform;
// }
// else {
// nativeView.frame = frame;
// }
nativeView.frame = frame;
const safeArea = this.getSafeArea();
const fullscreen = this.getFullscreenArea();
const locationOnScreen = this.getLocationInWindow();
const onScreenLeft = layout.toDevicePixels(layout.round(locationOnScreen.x));
const onScreenTop = layout.toDevicePixels(layout.round(locationOnScreen.y));
let left = layout.toDevicePixels(frame.origin.x);
let top = layout.toDevicePixels(frame.origin.y);
let width = layout.toDevicePixels(frame.size.width);
let height = layout.toDevicePixels(frame.size.height);
if (majorVersion > 10) {
// this._ios.insetsContentViewsToSafeArea = false;
let newLeft = left;
let newTop = top;
let newWidth = width;
let newHeight = height;
if (left !== 0 && onScreenLeft <= layout.toDevicePixels(safeArea.origin.x)) {
newLeft = layout.toDevicePixels(fullscreen.origin.x);
newWidth = width + onScreenLeft;
}
if (top !== 0 && onScreenTop <= layout.toDevicePixels(safeArea.origin.y)) {
newTop = layout.toDevicePixels(fullscreen.origin.y);
newHeight = height + onScreenTop;
}
if (width && width < layout.toDevicePixels(fullscreen.size.width) && onScreenLeft + width >= layout.toDevicePixels(safeArea.origin.x) + layout.toDevicePixels(safeArea.size.width)) {
newWidth = newWidth + (layout.toDevicePixels(fullscreen.size.width) - (onScreenLeft + width));
}
if (height && height < layout.toDevicePixels(fullscreen.size.height) && onScreenTop + height >= layout.toDevicePixels(safeArea.origin.y) + layout.toDevicePixels(safeArea.size.height)) {
newHeight = newHeight + (layout.toDevicePixels(fullscreen.size.height) - (onScreenTop + height));
}
const frameNew = CGRectMake(layout.toDeviceIndependentPixels(newLeft), layout.toDeviceIndependentPixels(newTop), layout.toDeviceIndependentPixels(newWidth), layout.toDeviceIndependentPixels(newHeight));
nativeView.frame = frameNew;
}
// if (leftInset || topInset) {
// const frameNew = CGRectMake(layout.toDeviceIndependentPixels(left), layout.toDeviceIndependentPixels(top), layout.toDeviceIndependentPixels(right - left + leftInset), layout.toDeviceIndependentPixels(bottom - top + topInset));
// 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, nativeView.frame.size.width, nativeView.frame.size.height);
// }
// }
return nativeView.frame;
}
private _layoutCell(cellView: View, indexPath: NSIndexPath): number {
if (cellView) {
const rowHeight = this._effectiveRowHeight;

View File

@@ -124,15 +124,6 @@ export class ScrollView extends ScrollViewBase {
this._contentMeasuredWidth = this.effectiveMinWidth;
this._contentMeasuredHeight = this.effectiveMinHeight;
// // `_automaticallyAdjustsScrollViewInsets` is set to true only if the first child
// // of UIViewController (Page, TabView e.g) is UIScrollView (ScrollView, ListView e.g).
// // On iOS 11 by default UIScrollView automatically adjusts the scroll view insets, but they s
// if (majorVersion > 10) {
// // Disable automatic adjustment of scroll view insets when ScrollView
// // is not the first child of UIViewController.
// this.nativeViewProtected.contentInsetAdjustmentBehavior = 2;
// }
if (child) {
let childSize: { measuredWidth: number; measuredHeight: number };
if (this.orientation === "vertical") {
@@ -141,10 +132,6 @@ export class ScrollView extends ScrollViewBase {
childSize = View.measureChild(this, child, layout.makeMeasureSpec(0, layout.UNSPECIFIED), heightMeasureSpec);
}
// const w = layout.toDeviceIndependentPixels(childSize.measuredWidth);
// const h = layout.toDeviceIndependentPixels(childSize.measuredHeight);
// this.nativeViewProtected.contentSize = CGSizeMake(w, h);
this._contentMeasuredWidth = Math.max(childSize.measuredWidth, this.effectiveMinWidth);
this._contentMeasuredHeight = Math.max(childSize.measuredHeight, this.effectiveMinHeight);
}
@@ -155,29 +142,20 @@ export class ScrollView extends ScrollViewBase {
this.setMeasuredDimension(widthAndState, heightAndState);
}
public onLayout(left: number, top: number, right: number, bottom: number, insets?: {left, top, right, bottom}): void {
public onLayout(left: number, top: number, right: number, bottom: number): void {
let width = (right - left);
let height = (bottom - top);
const nativeView = this.nativeViewProtected;
if (majorVersion > 10) {
// Disable automatic adjustment of scroll view insets
// Consider exposing this as property with all 4 modes
// https://developer.apple.com/documentation/uikit/uiscrollview/contentinsetadjustmentbehavior
this.nativeViewProtected.contentInsetAdjustmentBehavior = 2;
nativeView.contentInsetAdjustmentBehavior = 2;
}
// let verticalInset: number;
const nativeView = this.nativeViewProtected;
// const inset = nativeView.adjustedContentInset;
// // Prior iOS 11
// if (inset === undefined) {
// verticalInset = 0;
// // verticalInset = -layout.toDevicePixels(nativeView.contentOffset.y);
// // verticalInset += getTabBarHeight(this);
// } else {
// verticalInset = layout.toDevicePixels(inset.bottom + inset.top);
// }
const insets = this.getSafeAreaInsets();
if (this.orientation === "horizontal") {
width = Math.max(this._contentMeasuredWidth + insets.left + insets.right, width);
}
@@ -187,87 +165,6 @@ export class ScrollView extends ScrollViewBase {
nativeView.contentSize = CGSizeMake(layout.toDeviceIndependentPixels(width), layout.toDeviceIndependentPixels(height));
View.layoutChild(this, this.layoutView, insets.left, insets.top, width, height);
// if (this.orientation === "horizontal") {
// nativeView.contentSize = CGSizeMake(layout.toDeviceIndependentPixels(this._contentMeasuredWidth + insets.left + insets.right), layout.toDeviceIndependentPixels(height));
// View.layoutChild(this, this.layoutView, 0, 0, Math.max(this._contentMeasuredWidth + insets.left + insets.right, width), height);
// } else {
// nativeView.contentSize = CGSizeMake(layout.toDeviceIndependentPixels(width), layout.toDeviceIndependentPixels(this._contentMeasuredHeight + insets.top + insets.bottom));
// View.layoutChild(this, this.layoutView, 0, 0, width, Math.max(this._contentMeasuredHeight + insets.top + insets.bottom, height));
// }
}
public _setNativeViewFrame(nativeView: UIView, frame: CGRect) {
// if (!CGRectEqualToRect(nativeView.frame, frame)) {
// if (traceEnabled()) {
// traceWrite(this + ", Native setFrame: = " + NSStringFromCGRect(frame), traceCategories.Layout);
// }
// this._cachedFrame = frame;
// if (this._hasTransfrom) {
// // Always set identity transform before setting frame;
// const transform = nativeView.transform;
// nativeView.transform = CGAffineTransformIdentity;
// nativeView.frame = frame;
// nativeView.transform = transform;
// }
// else {
// nativeView.frame = frame;
// }
nativeView.frame = frame;
const safeArea = this.getSafeArea();
const fullscreen = this.getFullscreenArea();
const locationOnScreen = this.getLocationInWindow();
const onScreenLeft = layout.round(layout.toDevicePixels(locationOnScreen.x));
const onScreenTop = layout.round(layout.toDevicePixels(locationOnScreen.y));
let left = layout.toDevicePixels(frame.origin.x);
let top = layout.toDevicePixels(frame.origin.y);
let width = layout.toDevicePixels(frame.size.width);
let height = layout.toDevicePixels(frame.size.height);
if (majorVersion > 10) {
let newLeft = left;
let newTop = top;
let newWidth = width;
let newHeight = height;
if (left !== 0 && onScreenLeft <= layout.toDevicePixels(safeArea.origin.x)) {
newLeft = layout.toDevicePixels(fullscreen.origin.x);
newWidth = width + onScreenLeft;
}
if (top !== 0 && onScreenTop <= layout.toDevicePixels(safeArea.origin.y)) {
newTop = layout.toDevicePixels(fullscreen.origin.y);
newHeight = height + onScreenTop;
}
if (width && width < layout.toDevicePixels(fullscreen.size.width) && onScreenLeft + width >= layout.toDevicePixels(safeArea.origin.x) + layout.toDevicePixels(safeArea.size.width)) {
newWidth = newWidth + (layout.toDevicePixels(fullscreen.size.width) - (onScreenLeft + width));
}
if (height && height < layout.toDevicePixels(fullscreen.size.height) && onScreenTop + height >= layout.toDevicePixels(safeArea.origin.y) + layout.toDevicePixels(safeArea.size.height)) {
newHeight = newHeight + (layout.toDevicePixels(fullscreen.size.height) - (onScreenTop + height));
}
const frameNew = CGRectMake(layout.toDeviceIndependentPixels(newLeft), layout.toDeviceIndependentPixels(newTop), layout.toDeviceIndependentPixels(newWidth), layout.toDeviceIndependentPixels(newHeight));
nativeView.frame = frameNew;
}
// if (leftInset || topInset) {
// const frameNew = CGRectMake(layout.toDeviceIndependentPixels(left), layout.toDeviceIndependentPixels(top), layout.toDeviceIndependentPixels(right - left + leftInset), layout.toDeviceIndependentPixels(bottom - top + topInset));
// 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, nativeView.frame.size.width, nativeView.frame.size.height);
// }
// }
return nativeView.frame;
}
public _onOrientationChanged() {