diff --git a/tests/app/ui/layouts/flexbox-layout-tests.ts b/tests/app/ui/layouts/flexbox-layout-tests.ts index b0b817a20..3ab78c817 100644 --- a/tests/app/ui/layouts/flexbox-layout-tests.ts +++ b/tests/app/ui/layouts/flexbox-layout-tests.ts @@ -1911,6 +1911,20 @@ export const testWrap_childMargin_vertical = test( } ); +let activity_flexbox_with_proxy_view_container = () => getViews( + ` + + ` +); + +export const testFlexboxLayout_does_not_crash_with_proxy_view_container = test( + activity_flexbox_with_proxy_view_container, + noop, + ({root, flexbox}) => { + TKUnit.assert(flexbox.id === "flexbox", "FlexboxLayout actually there"); + } +); + // Omit testEmptyChildren // Omit testDivider_directionRow_verticalBeginning diff --git a/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts b/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts index 6304296bc..c369f6efa 100644 --- a/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts +++ b/tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts @@ -94,6 +94,28 @@ import makeMeasureSpec = layout.makeMeasureSpec; import getMeasureSpecMode = layout.getMeasureSpecMode; import getMeasureSpecSize = layout.getMeasureSpecSize; +// `eachLayoutChild` iterates over children, and we need more - indexed access. +// This class tries to accomodate that by collecting all children in an +// array no more than once per measure. +class MeasureContext { + private children: View[]; + + constructor(private owner: FlexboxLayout) { + this.children = []; + this.owner.eachLayoutChild((child) => { + this.children.push(child); + }); + } + + public get childrenCount(): number { + return this.children.length; + } + + public childAt(index: number): View { + return this.children[index]; + } +} + class FlexLine { _left: number = Number.MAX_VALUE; @@ -144,15 +166,17 @@ export class FlexboxLayout extends FlexboxLayoutBase { private _orderCache: number[]; private _flexLines: FlexLine[] = []; private _childrenFrozen: boolean[]; + private measureContext: MeasureContext; public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { + this.measureContext = new MeasureContext(this); // Omit: super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (this._isOrderChangedFromLastMeasurement) { this._reorderedIndices = this._createReorderedIndices(); } - if (!this._childrenFrozen || this._childrenFrozen.length < this.getChildrenCount()) { - this._childrenFrozen = new Array(this.getChildrenCount()); + if (!this._childrenFrozen || this._childrenFrozen.length < this.measureContext.childrenCount) { + this._childrenFrozen = new Array(this.measureContext.childrenCount); } switch (this.flexDirection) { @@ -177,13 +201,13 @@ export class FlexboxLayout extends FlexboxLayoutBase { child = null; } else { let reorderedIndex = this._reorderedIndices[index]; - child = this.getChildAt(reorderedIndex); + child = this.measureContext.childAt(reorderedIndex); } return child; } private _createReorderedIndices(): number[] { - let childCount = this.getChildrenCount(); + let childCount = this.measureContext.childrenCount; let orders = this._createOrders(childCount); return this._sortOrdersIntoReorderedIndices(childCount, orders); } @@ -206,7 +230,7 @@ export class FlexboxLayout extends FlexboxLayoutBase { private _createOrders(childCount: number): Order[] { let orders: Order[] = []; for (let i = 0; i < childCount; i++) { - let child = this.getChildAt(i); + let child = this.measureContext.childAt(i); let order = new Order(); order.order = FlexboxLayout.getOrder(child); order.index = i; @@ -216,7 +240,7 @@ export class FlexboxLayout extends FlexboxLayoutBase { } private get _isOrderChangedFromLastMeasurement(): boolean { - let childCount = this.getChildrenCount(); + let childCount = this.measureContext.childrenCount; if (!this._orderCache) { this._orderCache = []; } @@ -224,7 +248,7 @@ export class FlexboxLayout extends FlexboxLayoutBase { return true; } for (let i = 0; i < childCount; i++) { - let view = this.getChildAt(i); + let view = this.measureContext.childAt(i); if (view === null) { continue; } @@ -244,7 +268,7 @@ export class FlexboxLayout extends FlexboxLayoutBase { this._flexLines.length = 0; (() => { - let childCount = this.getChildrenCount(); + let childCount = this.measureContext.childrenCount; let paddingStart = FlexboxLayout.getPaddingStart(this); let paddingEnd = FlexboxLayout.getPaddingEnd(this); let largestHeightInRow = Number.MIN_VALUE; @@ -359,7 +383,7 @@ export class FlexboxLayout extends FlexboxLayoutBase { this._flexLines.length = 0; - let childCount = this.getChildrenCount(); + let childCount = this.measureContext.childrenCount; let paddingTop = this.effectivePaddingTop; let paddingBottom = this.effectivePaddingBottom; let largestWidthInColumn = Number.MIN_VALUE;