Skip to content

Commit cc18909

Browse files
authored
fix(core): FlexboxLayout nested views alignment corrections (NativeScript#10766)
1 parent f820dc1 commit cc18909

File tree

4 files changed

+89
-33
lines changed

4 files changed

+89
-33
lines changed
233 Bytes
Binary file not shown.

packages/core/ui/layouts/flexbox-layout/index.ios.ts

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class FlexLine {
6767
_dividerLengthInMainSize = 0;
6868
_crossSize = 0;
6969
_itemCount = 0;
70+
_goneItemCount = 0;
7071
_totalFlexGrow = 0;
7172
_totalFlexShrink = 0;
7273
_maxBaseline = 0;
@@ -95,6 +96,9 @@ class FlexLine {
9596
get itemCount(): number {
9697
return this._itemCount;
9798
}
99+
get layoutVisibleItemCount(): number {
100+
return this._itemCount - this._goneItemCount;
101+
}
98102
get totalFlexGrow(): number {
99103
return this._totalFlexGrow;
100104
}
@@ -249,6 +253,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
249253
continue;
250254
} else if (child.isCollapsed) {
251255
flexLine._itemCount++;
256+
flexLine._goneItemCount++;
252257
this._addFlexLineIfLastFlexItem(i, childCount, flexLine);
253258
continue;
254259
}
@@ -276,7 +281,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
276281
largestHeightInRow = Math.max(largestHeightInRow, child.getMeasuredHeight() + lp.effectiveMarginTop + lp.effectiveMarginBottom);
277282

278283
if (this._isWrapRequired(child, widthMode, widthSize, flexLine._mainSize, child.getMeasuredWidth() + lp.effectiveMarginLeft + lp.effectiveMarginRight, i, indexInFlexLine)) {
279-
if (flexLine.itemCount > 0) {
284+
if (flexLine.layoutVisibleItemCount > 0) {
280285
this._addFlexLine(flexLine);
281286
}
282287

@@ -318,11 +323,11 @@ export class FlexboxLayout extends FlexboxLayoutBase {
318323
if (this.flexWrap !== FlexWrap.WRAP_REVERSE) {
319324
let marginTop = flexLine._maxBaseline - FlexboxLayout.getBaseline(child);
320325
marginTop = Math.max(marginTop, lp.effectiveMarginTop);
321-
largestHeightInLine = Math.max(largestHeightInLine, child.getActualSize().height + marginTop + lp.effectiveMarginBottom);
326+
largestHeightInLine = Math.max(largestHeightInLine, child.getMeasuredHeight() + marginTop + lp.effectiveMarginBottom);
322327
} else {
323328
let marginBottom = flexLine._maxBaseline - child.getMeasuredHeight() + FlexboxLayout.getBaseline(child);
324329
marginBottom = Math.max(marginBottom, lp.effectiveMarginBottom);
325-
largestHeightInLine = Math.max(largestHeightInLine, child.getActualSize().height + lp.effectiveMarginTop + marginBottom);
330+
largestHeightInLine = Math.max(largestHeightInLine, child.getMeasuredHeight() + lp.effectiveMarginTop + marginBottom);
326331
}
327332
}
328333
flexLine._crossSize = largestHeightInLine;
@@ -359,6 +364,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
359364
continue;
360365
} else if (child.isCollapsed) {
361366
flexLine._itemCount++;
367+
flexLine._goneItemCount++;
362368
this._addFlexLineIfLastFlexItem(i, childCount, flexLine);
363369
continue;
364370
}
@@ -385,7 +391,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
385391
largestWidthInColumn = Math.max(largestWidthInColumn, child.getMeasuredWidth() + lp.effectiveMarginLeft + lp.effectiveMarginRight);
386392

387393
if (this._isWrapRequired(child, heightMode, heightSize, flexLine.mainSize, child.getMeasuredHeight() + lp.effectiveMarginTop + lp.effectiveMarginBottom, i, indexInFlexLine)) {
388-
if (flexLine._itemCount > 0) {
394+
if (flexLine.layoutVisibleItemCount > 0) {
389395
this._addFlexLine(flexLine);
390396
}
391397

@@ -447,7 +453,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
447453
}
448454

449455
private _addFlexLineIfLastFlexItem(childIndex: number, childCount: number, flexLine: FlexLine) {
450-
if (childIndex === childCount - 1 && flexLine.itemCount !== 0) {
456+
if (childIndex === childCount - 1 && flexLine.layoutVisibleItemCount !== 0) {
451457
this._addFlexLine(flexLine);
452458
}
453459
}
@@ -1012,16 +1018,20 @@ export class FlexboxLayout extends FlexboxLayoutBase {
10121018
childLeft = paddingLeft + (width - insets.left - insets.right - flexLine._mainSize) / 2.0;
10131019
childRight = width - paddingRight - (width - insets.left - insets.right - flexLine._mainSize) / 2.0;
10141020
break;
1015-
case JustifyContent.SPACE_AROUND:
1016-
if (flexLine._itemCount !== 0) {
1017-
spaceBetweenItem = (width - insets.left - insets.right - flexLine.mainSize) / flexLine._itemCount;
1021+
case JustifyContent.SPACE_AROUND: {
1022+
const visibleCount = flexLine.layoutVisibleItemCount;
1023+
if (visibleCount !== 0) {
1024+
spaceBetweenItem = (width - insets.left - insets.right - flexLine.mainSize) / visibleCount;
10181025
}
10191026
childLeft = paddingLeft + spaceBetweenItem / 2.0;
10201027
childRight = width - paddingRight - spaceBetweenItem / 2.0;
10211028
break;
1029+
}
10221030
case JustifyContent.SPACE_BETWEEN: {
1031+
const visibleCount = flexLine.layoutVisibleItemCount;
1032+
const denominator = visibleCount !== 1 ? visibleCount - 1 : 1.0;
1033+
10231034
childLeft = paddingLeft;
1024-
const denominator = flexLine.itemCount !== 1 ? flexLine.itemCount - 1 : 1.0;
10251035
spaceBetweenItem = (width - insets.left - insets.right - flexLine.mainSize) / denominator;
10261036
childRight = width - paddingRight;
10271037
break;
@@ -1156,16 +1166,20 @@ export class FlexboxLayout extends FlexboxLayoutBase {
11561166
childTop = paddingTop + (height - insets.top - insets.bottom - flexLine._mainSize) / 2.0;
11571167
childBottom = height - paddingBottom - (height - insets.top - insets.bottom - flexLine._mainSize) / 2.0;
11581168
break;
1159-
case JustifyContent.SPACE_AROUND:
1160-
if (flexLine._itemCount !== 0) {
1161-
spaceBetweenItem = (height - insets.top - insets.bottom - flexLine._mainSize) / flexLine.itemCount;
1169+
case JustifyContent.SPACE_AROUND: {
1170+
const visibleCount = flexLine.layoutVisibleItemCount;
1171+
if (visibleCount !== 0) {
1172+
spaceBetweenItem = (height - insets.top - insets.bottom - flexLine._mainSize) / visibleCount;
11621173
}
11631174
childTop = paddingTop + spaceBetweenItem / 2.0;
11641175
childBottom = height - paddingBottom - spaceBetweenItem / 2.0;
11651176
break;
1177+
}
11661178
case JustifyContent.SPACE_BETWEEN: {
1179+
const visibleCount = flexLine.layoutVisibleItemCount;
1180+
const denominator = visibleCount !== 1 ? visibleCount - 1 : 1.0;
1181+
11671182
childTop = paddingTop;
1168-
const denominator = flexLine.itemCount !== 1 ? flexLine.itemCount - 1 : 1.0;
11691183
spaceBetweenItem = (height - insets.top - insets.bottom - flexLine.mainSize) / denominator;
11701184
childBottom = height - paddingBottom;
11711185
break;

packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/FlexLine.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ public class FlexLine {
7070
*/
7171
int mItemCount;
7272

73+
/** Holds the count of the views whose visibilities are gone */
74+
int mGoneItemCount;
75+
7376
/**
7477
* @see {@link #getTotalFlexGrow()}
7578
*/
@@ -151,6 +154,13 @@ public int getItemCount() {
151154
return mItemCount;
152155
}
153156

157+
/**
158+
* @return the count of the views whose visibilities are not gone in this flex line.
159+
*/
160+
public int getLayoutVisibleItemCount() {
161+
return mItemCount - mGoneItemCount;
162+
}
163+
154164
/**
155165
* @return the sum of the flexGrow properties of the children included in this flex line
156166
*/

packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/FlexboxLayout.java

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ private void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
583583
continue;
584584
} else if (child.getVisibility() == View.GONE) {
585585
flexLine.mItemCount++;
586+
flexLine.mGoneItemCount++;
586587
addFlexLineIfLastFlexItem(i, childCount, flexLine);
587588
continue;
588589
}
@@ -627,7 +628,7 @@ private void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
627628
if (isWrapRequired(widthMode, widthSize, flexLine.mMainSize,
628629
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin, lp,
629630
i, indexInFlexLine)) {
630-
if (flexLine.mItemCount > 0) {
631+
if (flexLine.getLayoutVisibleItemCount() > 0) {
631632
addFlexLine(flexLine);
632633
}
633634

@@ -681,17 +682,18 @@ private void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
681682
for (int i = viewIndex; i < viewIndex + flexLine.mItemCount; i++) {
682683
View child = getReorderedChildAt(i);
683684
LayoutParams lp = (LayoutParams) child.getLayoutParams();
685+
684686
if (mFlexWrap != FLEX_WRAP_WRAP_REVERSE) {
685687
int marginTop = flexLine.mMaxBaseline - child.getBaseline();
686688
marginTop = Math.max(marginTop, lp.topMargin);
687689
largestHeightInLine = Math.max(largestHeightInLine,
688-
child.getHeight() + marginTop + lp.bottomMargin);
690+
child.getMeasuredHeight() + marginTop + lp.bottomMargin);
689691
} else {
690692
int marginBottom = flexLine.mMaxBaseline - child.getMeasuredHeight() +
691693
child.getBaseline();
692694
marginBottom = Math.max(marginBottom, lp.bottomMargin);
693695
largestHeightInLine = Math.max(largestHeightInLine,
694-
child.getHeight() + lp.topMargin + marginBottom);
696+
child.getMeasuredHeight() + lp.topMargin + marginBottom);
695697
}
696698
}
697699
flexLine.mCrossSize = largestHeightInLine;
@@ -745,6 +747,7 @@ private void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
745747
continue;
746748
} else if (child.getVisibility() == View.GONE) {
747749
flexLine.mItemCount++;
750+
flexLine.mGoneItemCount++;
748751
addFlexLineIfLastFlexItem(i, childCount, flexLine);
749752
continue;
750753
}
@@ -790,7 +793,7 @@ private void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
790793
if (isWrapRequired(heightMode, heightSize, flexLine.mMainSize,
791794
child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin, lp,
792795
i, indexInFlexLine)) {
793-
if (flexLine.mItemCount > 0) {
796+
if (flexLine.getLayoutVisibleItemCount() > 0) {
794797
addFlexLine(flexLine);
795798
}
796799

@@ -862,7 +865,7 @@ private void checkSizeConstraints(View view) {
862865
}
863866

864867
private void addFlexLineIfLastFlexItem(int childIndex, int childCount, FlexLine flexLine) {
865-
if (childIndex == childCount - 1 && flexLine.mItemCount != 0) {
868+
if (childIndex == childCount - 1 && flexLine.getLayoutVisibleItemCount() != 0) {
866869
// Add the flex line if this item is the last item
867870
addFlexLine(flexLine);
868871
}
@@ -1661,20 +1664,25 @@ private void layoutHorizontal(boolean isRtl, int left, int top, int right, int b
16611664
childLeft = paddingLeft + (width - flexLine.mMainSize) / 2f;
16621665
childRight = width - paddingRight - (width - flexLine.mMainSize) / 2f;
16631666
break;
1664-
case JUSTIFY_CONTENT_SPACE_AROUND:
1665-
if (flexLine.mItemCount != 0) {
1667+
case JUSTIFY_CONTENT_SPACE_AROUND: {
1668+
int visibleCount = flexLine.getLayoutVisibleItemCount();
1669+
if (visibleCount != 0) {
16661670
spaceBetweenItem = (width - flexLine.mMainSize)
1667-
/ (float) flexLine.mItemCount;
1671+
/ (float) visibleCount;
16681672
}
16691673
childLeft = paddingLeft + spaceBetweenItem / 2f;
16701674
childRight = width - paddingRight - spaceBetweenItem / 2f;
16711675
break;
1672-
case JUSTIFY_CONTENT_SPACE_BETWEEN:
1676+
}
1677+
case JUSTIFY_CONTENT_SPACE_BETWEEN: {
1678+
int visibleCount = flexLine.getLayoutVisibleItemCount();
1679+
float denominator = visibleCount != 1 ? visibleCount - 1 : 1f;
1680+
16731681
childLeft = paddingLeft;
1674-
float denominator = flexLine.mItemCount != 1 ? flexLine.mItemCount - 1 : 1f;
16751682
spaceBetweenItem = (width - flexLine.mMainSize) / denominator;
16761683
childRight = width - paddingRight;
16771684
break;
1685+
}
16781686
default:
16791687
throw new IllegalStateException(
16801688
"Invalid justifyContent is set: " + mJustifyContent);
@@ -1878,20 +1886,25 @@ private void layoutVertical(boolean isRtl, boolean fromBottomToTop, int left, in
18781886
childTop = paddingTop + (height - flexLine.mMainSize) / 2f;
18791887
childBottom = height - paddingBottom - (height - flexLine.mMainSize) / 2f;
18801888
break;
1881-
case JUSTIFY_CONTENT_SPACE_AROUND:
1882-
if (flexLine.mItemCount != 0) {
1889+
case JUSTIFY_CONTENT_SPACE_AROUND: {
1890+
int visibleCount = flexLine.getLayoutVisibleItemCount();
1891+
if (visibleCount != 0) {
18831892
spaceBetweenItem = (height - flexLine.mMainSize)
1884-
/ (float) flexLine.mItemCount;
1893+
/ (float) visibleCount;
18851894
}
18861895
childTop = paddingTop + spaceBetweenItem / 2f;
18871896
childBottom = height - paddingBottom - spaceBetweenItem / 2f;
18881897
break;
1889-
case JUSTIFY_CONTENT_SPACE_BETWEEN:
1898+
}
1899+
case JUSTIFY_CONTENT_SPACE_BETWEEN: {
1900+
int visibleCount = flexLine.getLayoutVisibleItemCount();
1901+
float denominator = visibleCount != 1 ? visibleCount - 1 : 1f;
1902+
18901903
childTop = paddingTop;
1891-
float denominator = flexLine.mItemCount != 1 ? flexLine.mItemCount - 1 : 1f;
18921904
spaceBetweenItem = (height - flexLine.mMainSize) / denominator;
18931905
childBottom = height - paddingBottom;
18941906
break;
1907+
}
18951908
default:
18961909
throw new IllegalStateException(
18971910
"Invalid justifyContent is set: " + mJustifyContent);
@@ -2085,6 +2098,11 @@ private void drawDividersHorizontal(Canvas canvas, boolean isRtl, boolean fromBo
20852098
FlexLine flexLine = mFlexLines.get(i);
20862099
for (int j = 0; j < flexLine.mItemCount; j++) {
20872100
View view = getReorderedChildAt(currentViewIndex);
2101+
2102+
if (view == null || view.getVisibility() == View.GONE) {
2103+
continue;
2104+
}
2105+
20882106
LayoutParams lp = (LayoutParams) view.getLayoutParams();
20892107

20902108
// Judge if the beginning or middle divider is needed
@@ -2165,6 +2183,11 @@ private void drawDividersVertical(Canvas canvas, boolean isRtl, boolean fromBott
21652183
// Draw horizontal dividers if needed
21662184
for (int j = 0; j < flexLine.mItemCount; j++) {
21672185
View view = getReorderedChildAt(currentViewIndex);
2186+
2187+
if (view == null || view.getVisibility() == View.GONE) {
2188+
continue;
2189+
}
2190+
21682191
LayoutParams lp = (LayoutParams) view.getLayoutParams();
21692192

21702193
// Judge if the beginning or middle divider is needed
@@ -2332,11 +2355,20 @@ public void setAlignContent(@AlignContent int alignContent) {
23322355
}
23332356

23342357
/**
2335-
* @return the flex lines composing this flex container. This method returns an unmodifiable
2336-
* list. Thus any changes of the returned list are not supported.
2358+
* @return the flex lines composing this flex container. This method returns a copy of the
2359+
* original list excluding a dummy flex line (flex line that doesn't have any flex items in it
2360+
* but used for the alignment along the cross axis).
2361+
* Thus any changes of the returned list are not reflected to the original list.
23372362
*/
23382363
public List<FlexLine> getFlexLines() {
2339-
return Collections.unmodifiableList(mFlexLines);
2364+
List<FlexLine> result = new ArrayList<>(mFlexLines.size());
2365+
for (FlexLine flexLine : mFlexLines) {
2366+
if (flexLine.getLayoutVisibleItemCount() == 0) {
2367+
continue;
2368+
}
2369+
result.add(flexLine);
2370+
}
2371+
return result;
23402372
}
23412373

23422374
/**
@@ -2535,7 +2567,7 @@ private boolean hasDividerBeforeFlexLine(int flexLineIndex) {
25352567

25362568
private boolean allFlexLinesAreDummyBefore(int flexLineIndex) {
25372569
for (int i = 0; i < flexLineIndex; i++) {
2538-
if (mFlexLines.get(i).mItemCount > 0) {
2570+
if (mFlexLines.get(i).getLayoutVisibleItemCount() > 0) {
25392571
return false;
25402572
}
25412573
}
@@ -2554,7 +2586,7 @@ private boolean hasEndDividerAfterFlexLine(int flexLineIndex) {
25542586
}
25552587

25562588
for (int i = flexLineIndex + 1; i < mFlexLines.size(); i++) {
2557-
if (mFlexLines.get(i).mItemCount > 0) {
2589+
if (mFlexLines.get(i).getLayoutVisibleItemCount() > 0) {
25582590
return false;
25592591
}
25602592
}

0 commit comments

Comments
 (0)