diff --git a/src/Core/src/Layouts/GridLayoutManager.cs b/src/Core/src/Layouts/GridLayoutManager.cs index 2741dca6a30a..e3370dc11de0 100644 --- a/src/Core/src/Layouts/GridLayoutManager.cs +++ b/src/Core/src/Layouts/GridLayoutManager.cs @@ -373,6 +373,9 @@ void KnownMeasurePass() { var cell = _cells[n]; + bool treatCellHeightAsAuto = TreatCellHeightAsAuto(cell); + bool treatCellWidthAsAuto = TreatCellWidthAsAuto(cell); + if (double.IsNaN(cell.MeasureHeight) || double.IsNaN(cell.MeasureWidth)) { // We still have some unknown measure constraints (* rows/columns that need to have @@ -380,7 +383,7 @@ void KnownMeasurePass() // second pass, once we know the constraints. cell.NeedsSecondPass = true; - if (!cell.IsColumnSpanAuto && !cell.IsRowSpanAuto) + if (!(treatCellHeightAsAuto || treatCellWidthAsAuto)) { // If neither span of this cell includes _any_ Auto values, then there's no reason // to measure it at all during this pass; we can skip it for now @@ -393,7 +396,7 @@ void KnownMeasurePass() var measure = MeasureCell(cell, measureWidth, measureHeight); - if (cell.IsColumnSpanAuto) + if (treatCellWidthAsAuto) { if (cell.ColumnSpan == 1) { @@ -405,7 +408,7 @@ void KnownMeasurePass() } } - if (cell.IsRowSpanAuto) + if (treatCellHeightAsAuto) { if (cell.RowSpan == 1) { @@ -971,15 +974,10 @@ void DetermineCellMeasureWidth(Cell cell) { UpdateKnownMeasureWidth(cell); } - else if (cell.IsColumnSpanAuto) + else if (TreatCellWidthAsAuto(cell)) { cell.MeasureWidth = double.PositiveInfinity; } - else if (cell.IsColumnSpanStar && double.IsInfinity(_gridWidthConstraint)) - { - // Because the Grid isn't horizontally constrained, we treat * columns as Auto - cell.MeasureWidth = double.PositiveInfinity; - } // For all other situations, we'll have to wait until we've measured the Auto columns } @@ -990,17 +988,44 @@ void DetermineCellMeasureHeight(Cell cell) { UpdateKnownMeasureHeight(cell); } - else if (cell.IsRowSpanAuto) + else if (TreatCellHeightAsAuto(cell)) { cell.MeasureHeight = double.PositiveInfinity; } - else if (cell.IsRowSpanStar && double.IsInfinity(_gridHeightConstraint)) + + // For all other situations, we'll have to wait until we've measured the Auto rows + } + + bool TreatCellWidthAsAuto(Cell cell) + { + if (cell.IsColumnSpanAuto) { - // Because the Grid isn't vertically constrained, we treat * rows as Auto - cell.MeasureHeight = double.PositiveInfinity; + return true; } - // For all other situations, we'll have to wait until we've measured the Auto rows + if (double.IsInfinity(_gridWidthConstraint) && cell.IsColumnSpanStar) + { + // Because the Grid isn't horizontally constrained, we treat * columns as Auto + return true; + } + + return false; + } + + bool TreatCellHeightAsAuto(Cell cell) + { + if (cell.IsRowSpanAuto) + { + return true; + } + + if (double.IsInfinity(_gridHeightConstraint) && cell.IsRowSpanStar) + { + // Because the Grid isn't vertically constrained, we treat * rows as Auto + return true; + } + + return false; } } diff --git a/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs b/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs index f11a4b46d862..864ea13a8b8e 100644 --- a/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs +++ b/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs @@ -7,6 +7,7 @@ using Microsoft.Maui.Layouts; using Microsoft.Maui.Primitives; using NSubstitute; +using NSubstitute.ReceivedExtensions; using Xunit; using static Microsoft.Maui.UnitTests.Layouts.LayoutTestHelpers; using LayoutAlignment = Microsoft.Maui.Primitives.LayoutAlignment; @@ -2378,5 +2379,53 @@ public void StarsExpandToFixedSizes() AssertArranged(view0, new Rect(0, 0, 100, 120)); } + + [Fact] + public void AutoStarColumnsRespectUnconstrainedHeight() + { + var grid = CreateGridLayout(columns: "Auto, *"); + + var view0 = CreateTestView(new Size(20, 20)); + view0.HorizontalLayoutAlignment.Returns(LayoutAlignment.Start); + view0.VerticalLayoutAlignment.Returns(LayoutAlignment.Start); + + SubstituteChildren(grid, view0); + SetLocation(grid, view0, col: 1); + + _ = MeasureAndArrange(grid, widthConstraint: 200, heightConstraint: double.PositiveInfinity); + + // The Grid only has one view; since we're measuring the Grid without height constraints, + // and the single view does not have an explicit height, then there should have been at least + // one measurement with an unconstrained height + view0.Received().Measure(Arg.Any(), double.PositiveInfinity); + + // The Auto column has no Views, so we expect it to have zero width; the single view should + // be arranged at the top left corner + AssertArranged(view0, new Rect(0, 0, 20, 20)); + } + + [Fact] + public void AutoStarRowsRespectUnconstrainedWidth() + { + var grid = CreateGridLayout(rows: "Auto, *"); + + var view0 = CreateTestView(new Size(20, 20)); + view0.HorizontalLayoutAlignment.Returns(LayoutAlignment.Start); + view0.VerticalLayoutAlignment.Returns(LayoutAlignment.Start); + + SubstituteChildren(grid, view0); + SetLocation(grid, view0, row: 1); + + _ = MeasureAndArrange(grid, widthConstraint: double.PositiveInfinity, heightConstraint: 200); + + // The Grid only has one view; since we're measuring the Grid without width constraints, + // and the single view does not have an explicit width, then there should have been at least + // one measurement with an unconstrained width + view0.Received().Measure(double.PositiveInfinity, Arg.Any()); + + // The Auto row has no Views, so we expect it to have zero height; the single view should + // be arranged at the top left corner + AssertArranged(view0, new Rect(0, 0, 20, 20)); + } } }