fix(ios): background styles after frame changed by safe area (#10661)

This commit is contained in:
Dimitris-Rafail Katsampas
2025-01-13 05:51:33 +02:00
committed by GitHub
parent 87742638d1
commit 1e86ed9da8
9 changed files with 47 additions and 57 deletions

View File

@ -1,5 +1,5 @@
// Definitions.
import type { Point, CustomLayoutView as CustomLayoutViewDefinition } from '.';
import type { Point, CustomLayoutView as CustomLayoutViewDefinition, Position } from '.';
import type { GestureTypes, GestureEventData } from '../../gestures';
// Types.
@ -577,12 +577,7 @@ export class View extends ViewCommon {
}
}
_getCurrentLayoutBounds(): {
left: number;
top: number;
right: number;
bottom: number;
} {
_getCurrentLayoutBounds(): Position {
if (this.nativeViewProtected && !this.isCollapsed) {
return {
left: this.nativeViewProtected.getLeft(),

View File

@ -64,6 +64,13 @@ export interface Point {
z?: number;
}
export interface Position {
top: number;
right: number;
bottom: number;
left: number;
}
/**
* The Size interface describes abstract dimensions in two dimensional space.
* It has two properties width and height, representing the width and height values of the size.
@ -857,7 +864,7 @@ export abstract class View extends ViewCommon {
/**
* Returns the iOS safe area insets of this view.
*/
public getSafeAreaInsets(): { left; top; right; bottom };
public getSafeAreaInsets(): Position;
/**
* Returns the location of this view in the window coordinate system.
@ -1013,12 +1020,7 @@ export abstract class View extends ViewCommon {
* Return view bounds.
* @private
*/
_getCurrentLayoutBounds(): {
left: number;
top: number;
right: number;
bottom: number;
};
_getCurrentLayoutBounds(): Position;
/**
* @private
*/

View File

@ -1,5 +1,5 @@
// Types.
import { Point, View as ViewDefinition } from '.';
import { Point, Position, View as ViewDefinition } from '.';
// Requires
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty } from './view-common';
@ -108,19 +108,31 @@ export class View extends ViewCommon implements ViewDefinition {
@profile
public layout(left: number, top: number, right: number, bottom: number, setFrame = true): void {
const { boundsChanged, sizeChanged } = this._setCurrentLayoutBounds(left, top, right, bottom);
const result = this._setCurrentLayoutBounds(left, top, right, bottom);
let { sizeChanged } = result;
if (setFrame) {
this.layoutNativeView(left, top, right, bottom);
}
const needsLayout = boundsChanged || (this._privateFlags & PFLAG_LAYOUT_REQUIRED) === PFLAG_LAYOUT_REQUIRED;
const needsLayout = result.boundsChanged || (this._privateFlags & PFLAG_LAYOUT_REQUIRED) === PFLAG_LAYOUT_REQUIRED;
if (needsLayout) {
let position = { left, top, right, bottom };
let position: Position;
if (this.nativeViewProtected && SDK_VERSION > 10) {
// on iOS 11+ it is possible to have a changed layout frame due to safe area insets
// get the frame and adjust the position, so that onLayout works correctly
const frame = this.nativeViewProtected.frame;
position = IOSHelper.getPositionFromFrame(frame);
position = IOSHelper.getPositionFromFrame(this.nativeViewProtected.frame);
if (!sizeChanged) {
// If frame has actually changed, there is the need to update view background and border styles as they depend on native view bounds
// To trigger the needed visual update, mark size as changed
if (position.left !== left || position.top !== top || position.right !== right || position.bottom !== bottom) {
sizeChanged = true;
}
}
} else {
position = { left, top, right, bottom };
}
this.onLayout(position.left, position.top, position.right, position.bottom);
@ -316,7 +328,7 @@ export class View extends ViewCommon implements ViewDefinition {
return null;
}
public getSafeAreaInsets(): { left; top; right; bottom } {
public getSafeAreaInsets(): Position {
const safeAreaInsets = this.nativeViewProtected && this.nativeViewProtected.safeAreaInsets;
const insets = { left: 0, top: 0, right: 0, bottom: 0 };
if (this.iosIgnoreSafeArea) {
@ -938,12 +950,7 @@ export class View extends ViewCommon implements ViewDefinition {
});
}
_getCurrentLayoutBounds(): {
left: number;
top: number;
right: number;
bottom: number;
} {
_getCurrentLayoutBounds(): Position {
const nativeView = this.nativeViewProtected;
if (nativeView && !this.isCollapsed) {
const frame = nativeView.frame;

View File

@ -1,5 +1,5 @@
// Definitions.
import { View as ViewDefinition, Point, Size, ShownModallyData } from '.';
import { View as ViewDefinition, Point, Size, ShownModallyData, Position } from '.';
import { booleanConverter, ShowModalOptions, ViewBase } from '../view-base';
import { getEventOrGestureName } from '../bindable';
@ -1066,12 +1066,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
return changed;
}
_getCurrentLayoutBounds(): {
left: number;
top: number;
right: number;
bottom: number;
} {
_getCurrentLayoutBounds(): Position {
return { left: 0, top: 0, right: 0, bottom: 0 };
}
@ -1110,7 +1105,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
return undefined;
}
public getSafeAreaInsets(): { left; top; right; bottom } {
public getSafeAreaInsets(): Position {
return { left: 0, top: 0, right: 0, bottom: 0 };
}

View File

@ -1,4 +1,4 @@
import { View } from '..';
import { Position, View } from '..';
export class ViewHelper {
/**
@ -60,8 +60,8 @@ export namespace IOSHelper {
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void;
export function updateConstraints(controller: any /* UIViewController */, owner: View): void;
export function layoutView(controller: any /* UIViewController */, owner: View): void;
export function getPositionFromFrame(frame: any /* CGRect */): { left; top; right; bottom };
export function getFrameFromPosition(position: { left; top; right; bottom }, insets?: { left; top; right; bottom }): any; /* CGRect */
export function getPositionFromFrame(frame: any /* CGRect */): Position;
export function getFrameFromPosition(position: Position, insets?: Position): any; /* CGRect */
export function shrinkToSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
export function expandBeyondSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
export class UILayoutViewController {

View File

@ -1,5 +1,5 @@
// Types
import { View } from '..';
import { Position, View } from '..';
// Requires
import { ViewHelper } from './view-helper-common';
@ -247,7 +247,7 @@ export class IOSHelper {
}
}
static getPositionFromFrame(frame: CGRect): { left; top; right; bottom } {
static getPositionFromFrame(frame: CGRect): Position {
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));
@ -256,7 +256,7 @@ export class IOSHelper {
return { left, right, top, bottom };
}
static getFrameFromPosition(position: { left; top; right; bottom }, insets?: { left; top; right; bottom }): CGRect {
static getFrameFromPosition(position: Position, insets?: Position): CGRect {
insets = insets || { left: 0, top: 0, right: 0, bottom: 0 };
const left = layout.toDeviceIndependentPixels(position.left + insets.left);

View File

@ -1,5 +1,5 @@
import { FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent, FlexboxLayoutBase, FlexBasisPercent, orderProperty, flexGrowProperty, flexShrinkProperty, flexWrapBeforeProperty, alignSelfProperty } from './flexbox-layout-common';
import { View } from '../../core/view';
import { Position, View } from '../../core/view';
import { layout } from '../../../utils';
export * from './flexbox-layout-common';
@ -977,7 +977,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
}
}
private _layoutHorizontal(isRtl: boolean, left: number, top: number, right: number, bottom: number, insets: { left; top; right; bottom }) {
private _layoutHorizontal(isRtl: boolean, left: number, top: number, right: number, bottom: number, insets: Position) {
// include insets
const paddingLeft = this.effectivePaddingLeft + insets.left;
const paddingTop = this.effectivePaddingTop + insets.top;
@ -1122,7 +1122,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
}
}
private _layoutVertical(isRtl: boolean, fromBottomToTop: boolean, left: number, top: number, right: number, bottom: number, insets: { left; top; right; bottom }) {
private _layoutVertical(isRtl: boolean, fromBottomToTop: boolean, left: number, top: number, right: number, bottom: number, insets: Position) {
const paddingLeft = this.effectivePaddingLeft + insets.left;
const paddingTop = this.effectivePaddingTop + insets.top;
const paddingRight = this.effectivePaddingRight + insets.right;

View File

@ -1,6 +1,6 @@
import { StackLayoutBase } from './stack-layout-common';
import { CoreTypes } from '../../../core-types';
import { View } from '../../core/view';
import { Position, View } from '../../core/view';
import { layout } from '../../../utils';
import { Trace } from '../../../trace';
@ -101,7 +101,7 @@ export class StackLayout extends StackLayoutBase {
}
}
private layoutVertical(left: number, top: number, right: number, bottom: number, insets: { left; top; right; bottom }): void {
private layoutVertical(left: number, top: number, right: number, bottom: number, insets: Position): void {
const paddingLeft = this.effectiveBorderLeftWidth + this.effectivePaddingLeft + insets.left;
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;
const paddingRight = this.effectiveBorderRightWidth + this.effectivePaddingRight + insets.right;
@ -135,7 +135,7 @@ export class StackLayout extends StackLayoutBase {
});
}
private layoutHorizontal(left: number, top: number, right: number, bottom: number, insets: { left; top; right; bottom }): void {
private layoutHorizontal(left: number, top: number, right: number, bottom: number, insets: Position): void {
const paddingLeft = this.effectiveBorderLeftWidth + this.effectivePaddingLeft + insets.left;
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;
const paddingRight = this.effectiveBorderRightWidth + this.effectivePaddingRight + insets.right;

View File

@ -1,9 +1,7 @@
import { ScrollEventData } from '../scroll-view';
import { CoreTypes } from '../../core-types';
import { Background as BackgroundDefinition } from './background';
import { View, Point } from '../core/view';
import { View, Point, Position } from '../core/view';
import { LinearGradient } from './linear-gradient';
import { Color } from '../../color';
import { Screen } from '../../platform';
import { isDataURI, isFileOrResourcePath, layout } from '../../utils';
import { ios as iosViewUtils, NativeScriptUIView } from '../utils';
@ -16,13 +14,6 @@ import { BackgroundClearFlags } from './background-common';
export * from './background-common';
interface Position {
top: number;
right: number;
bottom: number;
left: number;
}
interface BackgroundDrawParams {
repeatX: boolean;
repeatY: boolean;