mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 11:01:21 +08:00
fix(ios): background styles after frame changed by safe area (#10661)
This commit is contained in:

committed by
GitHub

parent
87742638d1
commit
1e86ed9da8
@ -1,5 +1,5 @@
|
|||||||
// Definitions.
|
// Definitions.
|
||||||
import type { Point, CustomLayoutView as CustomLayoutViewDefinition } from '.';
|
import type { Point, CustomLayoutView as CustomLayoutViewDefinition, Position } from '.';
|
||||||
import type { GestureTypes, GestureEventData } from '../../gestures';
|
import type { GestureTypes, GestureEventData } from '../../gestures';
|
||||||
|
|
||||||
// Types.
|
// Types.
|
||||||
@ -577,12 +577,7 @@ export class View extends ViewCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCurrentLayoutBounds(): {
|
_getCurrentLayoutBounds(): Position {
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
right: number;
|
|
||||||
bottom: number;
|
|
||||||
} {
|
|
||||||
if (this.nativeViewProtected && !this.isCollapsed) {
|
if (this.nativeViewProtected && !this.isCollapsed) {
|
||||||
return {
|
return {
|
||||||
left: this.nativeViewProtected.getLeft(),
|
left: this.nativeViewProtected.getLeft(),
|
||||||
|
16
packages/core/ui/core/view/index.d.ts
vendored
16
packages/core/ui/core/view/index.d.ts
vendored
@ -64,6 +64,13 @@ export interface Point {
|
|||||||
z?: number;
|
z?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Position {
|
||||||
|
top: number;
|
||||||
|
right: number;
|
||||||
|
bottom: number;
|
||||||
|
left: number;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Size interface describes abstract dimensions in two dimensional space.
|
* 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.
|
* 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.
|
* 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.
|
* Returns the location of this view in the window coordinate system.
|
||||||
@ -1013,12 +1020,7 @@ export abstract class View extends ViewCommon {
|
|||||||
* Return view bounds.
|
* Return view bounds.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getCurrentLayoutBounds(): {
|
_getCurrentLayoutBounds(): Position;
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
right: number;
|
|
||||||
bottom: number;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Types.
|
// Types.
|
||||||
import { Point, View as ViewDefinition } from '.';
|
import { Point, Position, View as ViewDefinition } from '.';
|
||||||
|
|
||||||
// Requires
|
// Requires
|
||||||
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty } from './view-common';
|
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty } from './view-common';
|
||||||
@ -108,19 +108,31 @@ export class View extends ViewCommon implements ViewDefinition {
|
|||||||
|
|
||||||
@profile
|
@profile
|
||||||
public layout(left: number, top: number, right: number, bottom: number, setFrame = true): void {
|
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) {
|
if (setFrame) {
|
||||||
this.layoutNativeView(left, top, right, bottom);
|
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) {
|
if (needsLayout) {
|
||||||
let position = { left, top, right, bottom };
|
let position: Position;
|
||||||
|
|
||||||
if (this.nativeViewProtected && SDK_VERSION > 10) {
|
if (this.nativeViewProtected && SDK_VERSION > 10) {
|
||||||
// on iOS 11+ it is possible to have a changed layout frame due to safe area insets
|
// 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
|
// get the frame and adjust the position, so that onLayout works correctly
|
||||||
const frame = this.nativeViewProtected.frame;
|
position = IOSHelper.getPositionFromFrame(this.nativeViewProtected.frame);
|
||||||
position = IOSHelper.getPositionFromFrame(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);
|
this.onLayout(position.left, position.top, position.right, position.bottom);
|
||||||
@ -316,7 +328,7 @@ export class View extends ViewCommon implements ViewDefinition {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSafeAreaInsets(): { left; top; right; bottom } {
|
public getSafeAreaInsets(): Position {
|
||||||
const safeAreaInsets = this.nativeViewProtected && this.nativeViewProtected.safeAreaInsets;
|
const safeAreaInsets = this.nativeViewProtected && this.nativeViewProtected.safeAreaInsets;
|
||||||
const insets = { left: 0, top: 0, right: 0, bottom: 0 };
|
const insets = { left: 0, top: 0, right: 0, bottom: 0 };
|
||||||
if (this.iosIgnoreSafeArea) {
|
if (this.iosIgnoreSafeArea) {
|
||||||
@ -938,12 +950,7 @@ export class View extends ViewCommon implements ViewDefinition {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCurrentLayoutBounds(): {
|
_getCurrentLayoutBounds(): Position {
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
right: number;
|
|
||||||
bottom: number;
|
|
||||||
} {
|
|
||||||
const nativeView = this.nativeViewProtected;
|
const nativeView = this.nativeViewProtected;
|
||||||
if (nativeView && !this.isCollapsed) {
|
if (nativeView && !this.isCollapsed) {
|
||||||
const frame = nativeView.frame;
|
const frame = nativeView.frame;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Definitions.
|
// 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 { booleanConverter, ShowModalOptions, ViewBase } from '../view-base';
|
||||||
import { getEventOrGestureName } from '../bindable';
|
import { getEventOrGestureName } from '../bindable';
|
||||||
@ -1066,12 +1066,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCurrentLayoutBounds(): {
|
_getCurrentLayoutBounds(): Position {
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
right: number;
|
|
||||||
bottom: number;
|
|
||||||
} {
|
|
||||||
return { left: 0, top: 0, right: 0, bottom: 0 };
|
return { left: 0, top: 0, right: 0, bottom: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,7 +1105,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSafeAreaInsets(): { left; top; right; bottom } {
|
public getSafeAreaInsets(): Position {
|
||||||
return { left: 0, top: 0, right: 0, bottom: 0 };
|
return { left: 0, top: 0, right: 0, bottom: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { View } from '..';
|
import { Position, View } from '..';
|
||||||
|
|
||||||
export class ViewHelper {
|
export class ViewHelper {
|
||||||
/**
|
/**
|
||||||
@ -60,8 +60,8 @@ export namespace IOSHelper {
|
|||||||
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void;
|
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void;
|
||||||
export function updateConstraints(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 layoutView(controller: any /* UIViewController */, owner: View): void;
|
||||||
export function getPositionFromFrame(frame: any /* CGRect */): { left; top; right; bottom };
|
export function getPositionFromFrame(frame: any /* CGRect */): Position;
|
||||||
export function getFrameFromPosition(position: { left; top; right; bottom }, insets?: { left; top; right; bottom }): any; /* CGRect */
|
export function getFrameFromPosition(position: Position, insets?: Position): any; /* CGRect */
|
||||||
export function shrinkToSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
|
export function shrinkToSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
|
||||||
export function expandBeyondSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
|
export function expandBeyondSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */
|
||||||
export class UILayoutViewController {
|
export class UILayoutViewController {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Types
|
// Types
|
||||||
import { View } from '..';
|
import { Position, View } from '..';
|
||||||
|
|
||||||
// Requires
|
// Requires
|
||||||
import { ViewHelper } from './view-helper-common';
|
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 left = layout.round(layout.toDevicePixels(frame.origin.x));
|
||||||
const top = layout.round(layout.toDevicePixels(frame.origin.y));
|
const top = layout.round(layout.toDevicePixels(frame.origin.y));
|
||||||
const right = layout.round(layout.toDevicePixels(frame.origin.x + frame.size.width));
|
const right = layout.round(layout.toDevicePixels(frame.origin.x + frame.size.width));
|
||||||
@ -256,7 +256,7 @@ export class IOSHelper {
|
|||||||
return { left, right, top, bottom };
|
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 };
|
insets = insets || { left: 0, top: 0, right: 0, bottom: 0 };
|
||||||
|
|
||||||
const left = layout.toDeviceIndependentPixels(position.left + insets.left);
|
const left = layout.toDeviceIndependentPixels(position.left + insets.left);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent, FlexboxLayoutBase, FlexBasisPercent, orderProperty, flexGrowProperty, flexShrinkProperty, flexWrapBeforeProperty, alignSelfProperty } from './flexbox-layout-common';
|
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';
|
import { layout } from '../../../utils';
|
||||||
|
|
||||||
export * from './flexbox-layout-common';
|
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
|
// include insets
|
||||||
const paddingLeft = this.effectivePaddingLeft + insets.left;
|
const paddingLeft = this.effectivePaddingLeft + insets.left;
|
||||||
const paddingTop = this.effectivePaddingTop + insets.top;
|
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 paddingLeft = this.effectivePaddingLeft + insets.left;
|
||||||
const paddingTop = this.effectivePaddingTop + insets.top;
|
const paddingTop = this.effectivePaddingTop + insets.top;
|
||||||
const paddingRight = this.effectivePaddingRight + insets.right;
|
const paddingRight = this.effectivePaddingRight + insets.right;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { StackLayoutBase } from './stack-layout-common';
|
import { StackLayoutBase } from './stack-layout-common';
|
||||||
import { CoreTypes } from '../../../core-types';
|
import { CoreTypes } from '../../../core-types';
|
||||||
import { View } from '../../core/view';
|
import { Position, View } from '../../core/view';
|
||||||
import { layout } from '../../../utils';
|
import { layout } from '../../../utils';
|
||||||
import { Trace } from '../../../trace';
|
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 paddingLeft = this.effectiveBorderLeftWidth + this.effectivePaddingLeft + insets.left;
|
||||||
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;
|
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;
|
||||||
const paddingRight = this.effectiveBorderRightWidth + this.effectivePaddingRight + insets.right;
|
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 paddingLeft = this.effectiveBorderLeftWidth + this.effectivePaddingLeft + insets.left;
|
||||||
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;
|
const paddingTop = this.effectiveBorderTopWidth + this.effectivePaddingTop + insets.top;
|
||||||
const paddingRight = this.effectiveBorderRightWidth + this.effectivePaddingRight + insets.right;
|
const paddingRight = this.effectiveBorderRightWidth + this.effectivePaddingRight + insets.right;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { ScrollEventData } from '../scroll-view';
|
import { ScrollEventData } from '../scroll-view';
|
||||||
import { CoreTypes } from '../../core-types';
|
|
||||||
import { Background as BackgroundDefinition } from './background';
|
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 { LinearGradient } from './linear-gradient';
|
||||||
import { Color } from '../../color';
|
|
||||||
import { Screen } from '../../platform';
|
import { Screen } from '../../platform';
|
||||||
import { isDataURI, isFileOrResourcePath, layout } from '../../utils';
|
import { isDataURI, isFileOrResourcePath, layout } from '../../utils';
|
||||||
import { ios as iosViewUtils, NativeScriptUIView } from '../utils';
|
import { ios as iosViewUtils, NativeScriptUIView } from '../utils';
|
||||||
@ -16,13 +14,6 @@ import { BackgroundClearFlags } from './background-common';
|
|||||||
|
|
||||||
export * from './background-common';
|
export * from './background-common';
|
||||||
|
|
||||||
interface Position {
|
|
||||||
top: number;
|
|
||||||
right: number;
|
|
||||||
bottom: number;
|
|
||||||
left: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BackgroundDrawParams {
|
interface BackgroundDrawParams {
|
||||||
repeatX: boolean;
|
repeatX: boolean;
|
||||||
repeatY: boolean;
|
repeatY: boolean;
|
||||||
|
Reference in New Issue
Block a user