@@ -343,6 +343,10 @@ private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpe
343343 // We measure all children whose width specification policy is WrapContent without weight.
344344 // After 1st phase, remaining width of parent is accumulated to calculate width of children
345345 // whose width specification policy is MatchParent.
346+ widthSpecSize = widthMeasureSpec . GetSize ( ) . AsDecimal ( ) ;
347+ float lastEnd = 0f ;
348+ float beginBound = 0f ;
349+ float endBound = 0f ;
346350 foreach ( var childLayout in LayoutChildren )
347351 {
348352 if ( ! childLayout . SetPositionByLayout || ! ( childLayout . Owner . Visibility ) )
@@ -372,21 +376,26 @@ private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpe
372376 // Then, child layout1's size is 30 and child layout2's size is 50.
373377 if ( ( childDesiredWidth == LayoutParamPolicies . WrapContent ) || ( ( childDesiredWidth >= 0 ) && ( ! useRemainingWidth ) ) )
374378 {
375- var measurableWidth = Math . Max ( widthMeasureSpec . GetSize ( ) . AsDecimal ( ) - ( totalLength + CellPadding . Width * childrenWrapContentCount ) , 0 ) ;
379+ var lastEndPlusCellPadding = lastEnd + ( childrenWrapContentCount == 0 ? 0 : CellPadding . Width ) ;
380+ var measurableWidth = Math . Max ( Math . Min ( widthSpecSize , widthSpecSize - lastEndPlusCellPadding ) , 0 ) ;
376381 var measurableWidthSpec = new MeasureSpecification ( new LayoutLength ( measurableWidth ) , widthMeasureSpec . GetMode ( ) ) ;
377382 MeasureChildWithMargins ( childLayout , measurableWidthSpec , new LayoutLength ( 0 ) , heightMeasureSpec , new LayoutLength ( 0 ) ) ;
378383
379384 float childMeasuredWidth = childLayout . MeasuredWidth . Size . AsDecimal ( ) ;
380385
386+ beginBound = Math . Min ( beginBound , lastEndPlusCellPadding ) ;
387+
381388 if ( childMeasuredWidth < 0 )
382389 {
383- totalLength = Math . Max ( totalLength , totalLength + childMarginWidth ) ;
390+ lastEnd = lastEndPlusCellPadding + childMarginWidth ;
384391 }
385392 else
386393 {
387- totalLength = Math . Max ( totalLength , totalLength + childMeasuredWidth + childMarginWidth ) ;
394+ lastEnd = lastEndPlusCellPadding + childMeasuredWidth + childMarginWidth ;
388395 }
389396
397+ endBound = Math . Max ( endBound , lastEnd ) ;
398+
390399 childrenWrapContentCount ++ ;
391400 }
392401
@@ -400,14 +409,18 @@ private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpe
400409 }
401410 } // 1ST PHASE foreach
402411
403- totalLength = Math . Max ( totalLength , totalLength + CellPadding . Width * ( childrenCount - 1 ) + Padding . Start + Padding . End ) ;
412+ // If childrenWrapContentCount is less than 2, then CellPadding is not added to endBound and beginBound.
413+ // So Math.Max(childrenWrapContentCount - 1, 0) is used to be multiplied to CellPadding.
414+ totalLength = endBound - beginBound + CellPadding . Width * ( childrenCount - 1 - Math . Max ( childrenWrapContentCount - 1 , 0 ) ) ;
415+ totalLength = Math . Max ( totalLength , totalLength + Padding . Start + Padding . End ) ;
404416 float widthSize = Math . Max ( totalLength , SuggestedMinimumWidth . AsDecimal ( ) ) ;
405417 MeasuredSize widthSizeAndState = ResolveSizeAndState ( new LayoutLength ( widthSize ) , widthMeasureSpec , MeasuredSize . StateType . MeasuredSizeOK ) ;
406418 widthSize = widthSizeAndState . Size . AsDecimal ( ) ;
407419
408420 float remainingWidth = widthSize - totalLength ;
409421 float totalWeightLength = 0.0f ;
410422
423+ var childWidthMeasureSpec = new MeasureSpecification ( widthMeasureSpec . GetSize ( ) , widthMeasureSpec . GetMode ( ) ) ;
411424 if ( remainingWidth > 0 )
412425 {
413426 // 2ND PHASE:
@@ -434,7 +447,9 @@ private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpe
434447 {
435448 // In MeasureChildWithMargins(), it is assumed that widthMeasureSpec includes Padding.Start and Padding.End.
436449 // Therefore, Padding.Start and Padding.End are added to widthMeasureSpec.GetSize() before it is passed to MeasureChildWithMargins().
437- widthMeasureSpec . SetSize ( new LayoutLength ( ( int ) ( remainingWidth / childrenMatchParentCount ) + Padding . Start + Padding . End ) ) ;
450+ // If CellPadding is very big negative value, then remaining / childrenMatchParentCount may exceed constraint.
451+ // So use the minimum between constraint and remaining / childrenMatchParentCount + padding.
452+ childWidthMeasureSpec . SetSize ( new LayoutLength ( Math . Min ( widthMeasureSpec . GetSize ( ) . AsDecimal ( ) , ( int ) ( remainingWidth / childrenMatchParentCount ) + Padding . Start + Padding . End ) ) ) ;
438453 needToMeasure = true ;
439454 }
440455 // RelativeLayout's MatchParent children should not fill to the RelativeLayout.
@@ -457,7 +472,7 @@ private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpe
457472
458473 if ( needToMeasure == true )
459474 {
460- MeasureChildWithMargins ( childLayout , widthMeasureSpec , new LayoutLength ( 0 ) , heightMeasureSpec , new LayoutLength ( 0 ) ) ;
475+ MeasureChildWithMargins ( childLayout , childWidthMeasureSpec , new LayoutLength ( 0 ) , heightMeasureSpec , new LayoutLength ( 0 ) ) ;
461476 }
462477
463478 if ( ( childWeight > 0 ) && ( ( childDesiredWidth == LayoutParamPolicies . MatchParent ) || ( childDesiredWidth == 0 ) ) )
@@ -593,6 +608,10 @@ private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpeci
593608 // We measure all children whose height specification policy is WrapContent without weight.
594609 // After 1st phase, remaining height of parent is accumulated to calculate height of children
595610 // whose height specification policy is MatchParent.
611+ heightSpecSize = heightMeasureSpec . GetSize ( ) . AsDecimal ( ) ;
612+ float lastEnd = 0f ;
613+ float beginBound = 0f ;
614+ float endBound = 0f ;
596615 foreach ( var childLayout in LayoutChildren )
597616 {
598617 if ( ! childLayout . SetPositionByLayout || ! ( childLayout . Owner . Visibility ) )
@@ -622,21 +641,26 @@ private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpeci
622641 // Then, child layout1's size is 30 and child layout2's size is 50.
623642 if ( ( childDesiredHeight == LayoutParamPolicies . WrapContent ) || ( ( childDesiredHeight >= 0 ) && ( ! useRemainingHeight ) ) )
624643 {
625- var measurableHeight = Math . Max ( heightMeasureSpec . GetSize ( ) . AsDecimal ( ) - ( totalLength + CellPadding . Height * childrenWrapContentCount ) , 0 ) ;
644+ var lastEndPlusCellPadding = lastEnd + ( childrenWrapContentCount == 0 ? 0 : CellPadding . Height ) ;
645+ var measurableHeight = Math . Max ( Math . Min ( heightSpecSize , heightSpecSize - lastEndPlusCellPadding ) , 0 ) ;
626646 var measurableHeightSpec = new MeasureSpecification ( new LayoutLength ( measurableHeight ) , heightMeasureSpec . GetMode ( ) ) ;
627647 MeasureChildWithMargins ( childLayout , widthMeasureSpec , new LayoutLength ( 0 ) , measurableHeightSpec , new LayoutLength ( 0 ) ) ;
628648
629649 float childMeasuredHeight = childLayout . MeasuredHeight . Size . AsDecimal ( ) ;
630650
651+ beginBound = Math . Min ( beginBound , lastEndPlusCellPadding ) ;
652+
631653 if ( childMeasuredHeight < 0 )
632654 {
633- totalLength = Math . Max ( totalLength , totalLength + childMarginHeight ) ;
655+ lastEnd = lastEndPlusCellPadding + childMarginHeight ;
634656 }
635657 else
636658 {
637- totalLength = Math . Max ( totalLength , totalLength + childMeasuredHeight + childMarginHeight ) ;
659+ lastEnd = lastEndPlusCellPadding + childMeasuredHeight + childMarginHeight ;
638660 }
639661
662+ endBound = Math . Max ( endBound , lastEnd ) ;
663+
640664 childrenWrapContentCount ++ ;
641665 }
642666
@@ -650,14 +674,18 @@ private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpeci
650674 }
651675 } // 1ST PHASE foreach
652676
653- totalLength = Math . Max ( totalLength , totalLength + CellPadding . Height * ( childrenCount - 1 ) + Padding . Top + Padding . Bottom ) ;
677+ // If childrenWrapContentCount is less than 2, then CellPadding is not added to endBound and beginBound.
678+ // So Math.Max(childrenWrapContentCount - 1, 0) is used to be multiplied to CellPadding.
679+ totalLength = endBound - beginBound + CellPadding . Height * ( childrenCount - 1 - Math . Max ( childrenWrapContentCount - 1 , 0 ) ) ;
680+ totalLength = Math . Max ( totalLength , totalLength + Padding . Top + Padding . Bottom ) ;
654681 float heightSize = Math . Max ( totalLength , SuggestedMinimumHeight . AsDecimal ( ) ) ;
655682 MeasuredSize heightSizeAndState = ResolveSizeAndState ( new LayoutLength ( heightSize ) , heightMeasureSpec , MeasuredSize . StateType . MeasuredSizeOK ) ;
656683 heightSize = heightSizeAndState . Size . AsDecimal ( ) ;
657684
658685 float remainingHeight = heightSize - totalLength ;
659686 float totalWeightLength = 0.0f ;
660687
688+ var childHeightMeasureSpec = new MeasureSpecification ( heightMeasureSpec . GetSize ( ) , heightMeasureSpec . GetMode ( ) ) ;
661689 if ( remainingHeight > 0 )
662690 {
663691 // 2ND PHASE:
@@ -684,7 +712,9 @@ private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpeci
684712 {
685713 // In MeasureChildWithMargins(), it is assumed that heightMeasureSpec includes Padding.Top and Padding.Bottom.
686714 // Therefore, Padding.Top and Padding.Bottom are added to heightMeasureSpec.GetSize() before it is passed to MeasureChildWithMargins().
687- heightMeasureSpec . SetSize ( new LayoutLength ( ( int ) ( remainingHeight / childrenMatchParentCount ) + Padding . Top + Padding . Bottom ) ) ;
715+ // If CellPadding is very big negative value, then remaining / childrenMatchParentCount may exceed constraint.
716+ // So use the minimum between constraint and remaining / childrenMatchParentCount + padding.
717+ childHeightMeasureSpec . SetSize ( new LayoutLength ( Math . Min ( heightMeasureSpec . GetSize ( ) . AsDecimal ( ) , ( int ) ( remainingHeight / childrenMatchParentCount ) + Padding . Top + Padding . Bottom ) ) ) ;
688718 needToMeasure = true ;
689719 }
690720 // RelativeLayout's MatchParent children should not fill to the RelativeLayout.
@@ -707,7 +737,7 @@ private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpeci
707737
708738 if ( needToMeasure == true )
709739 {
710- MeasureChildWithMargins ( childLayout , widthMeasureSpec , new LayoutLength ( 0 ) , heightMeasureSpec , new LayoutLength ( 0 ) ) ;
740+ MeasureChildWithMargins ( childLayout , widthMeasureSpec , new LayoutLength ( 0 ) , childHeightMeasureSpec , new LayoutLength ( 0 ) ) ;
711741 }
712742
713743 if ( ( childWeight > 0 ) && ( ( childDesiredHeight == LayoutParamPolicies . MatchParent ) || ( childDesiredHeight == 0 ) ) )
@@ -819,7 +849,9 @@ private void LayoutHorizontal(LayoutLength left, LayoutLength top, LayoutLength
819849 var LinearChildren = IterateLayoutChildren ( ) ;
820850 int count = LinearChildren . Count ( ) ;
821851
822- float totalLength = 0 ;
852+ float lastEnd = 0f ;
853+ float beginBound = 0f ;
854+ float endBound = 0f ;
823855 int validChildCount = 0 ;
824856 foreach ( var childLayout in LayoutChildren )
825857 {
@@ -831,11 +863,14 @@ private void LayoutHorizontal(LayoutLength left, LayoutLength top, LayoutLength
831863 var childWidthSize = childLayout . MeasuredWidth . Size . AsDecimal ( ) ;
832864 if ( childWidthSize > 0 )
833865 {
866+ var lastEndPlusCellPadding = lastEnd + ( validChildCount == 0 ? 0 : CellPadding . Width ) ;
867+ beginBound = Math . Min ( beginBound , lastEndPlusCellPadding ) ;
868+ lastEnd = lastEndPlusCellPadding + childWidthSize + childLayout . Margin . Start + childLayout . Margin . End ;
869+ endBound = Math . Max ( endBound , lastEnd ) ;
834870 validChildCount ++ ;
835- totalLength += childWidthSize + childLayout . Margin . Start + childLayout . Margin . End ;
836871 }
837872 }
838- totalLength += CellPadding . Width * ( validChildCount - 1 ) ;
873+ float totalLength = endBound - beginBound ;
839874
840875 var leftPadding = isLayoutRtl ? Padding . End : Padding . Start ;
841876
@@ -933,7 +968,9 @@ private void LayoutVertical(LayoutLength left, LayoutLength top, LayoutLength ri
933968 var LinearChildren = IterateLayoutChildren ( ) ;
934969 int count = LinearChildren . Count < LayoutItem > ( ) ;
935970
936- float totalLength = 0 ;
971+ float lastEnd = 0f ;
972+ float beginBound = 0f ;
973+ float endBound = 0f ;
937974 int validChildCount = 0 ;
938975 foreach ( var childLayout in LayoutChildren )
939976 {
@@ -945,11 +982,14 @@ private void LayoutVertical(LayoutLength left, LayoutLength top, LayoutLength ri
945982 var childHeightSize = childLayout . MeasuredHeight . Size . AsDecimal ( ) ;
946983 if ( childHeightSize > 0 )
947984 {
985+ var lastEndPlusCellPadding = lastEnd + ( validChildCount == 0 ? 0 : CellPadding . Height ) ;
986+ beginBound = Math . Min ( beginBound , lastEndPlusCellPadding ) ;
987+ lastEnd = lastEndPlusCellPadding + childHeightSize + childLayout . Margin . Top + childLayout . Margin . Bottom ;
988+ endBound = Math . Max ( endBound , lastEnd ) ;
948989 validChildCount ++ ;
949- totalLength += childHeightSize + childLayout . Margin . Top + childLayout . Margin . Bottom ;
950990 }
951991 }
952- totalLength += CellPadding . Height * ( validChildCount - 1 ) ;
992+ float totalLength = endBound - beginBound ;
953993
954994 switch ( VerticalAlignment )
955995 {
0 commit comments