Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix layouting on mobile #18261

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -638,16 +638,10 @@ public Task MeasureWithNan() =>
Assert.AreEqual(new Size(double.PositiveInfinity, double.PositiveInfinity), SUT.MeasureOverrides.Last());
Assert.AreEqual(new Size(0, 0), SUT.DesiredSize);

#if __CROSSRUNTIME__
// Unlike WinUI, we don't crash.
SUT.Measure(new Size(double.NaN, double.NaN));
SUT.Measure(new Size(42.0, double.NaN));
SUT.Measure(new Size(double.NaN, 42.0));
#else
Assert.ThrowsException<InvalidOperationException>(() => SUT.Measure(new Size(double.NaN, double.NaN)));
Assert.ThrowsException<InvalidOperationException>(() => SUT.Measure(new Size(42.0, double.NaN)));
Assert.ThrowsException<InvalidOperationException>(() => SUT.Measure(new Size(double.NaN, 42.0)));
#endif
});

[TestMethod]
Expand Down Expand Up @@ -913,9 +907,6 @@ public async Task When_Native_Parent_And_Measure_Infinite()

panel.Measure(new Size(1000, 1000));

var measuredHeightLogical = Math.Round(Uno.UI.ViewHelper.PhysicalToLogicalPixels(outer.MeasuredHeight));
Assert.AreEqual(InnerBorderHeight, measuredHeightLogical);

outer.Arrange(new Rect(0, 0, 1000, 1000));
var actualHeight = Math.Round(outer.ActualHeight);
Assert.AreEqual(InnerBorderHeight, actualHeight);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,7 @@ public void When_LayoutUpdated()

using (new AssertionScope())
{
#if __ANDROID__
// Android has an issue where LayoutUpdate is called twice, caused by the presence
// of two calls to arrange (Arrange, ArrangeElement(this)) in FrameworkElement.
// Failing to call the first Arrange makes some elements fail to have a proper size in
// some yet unknown conditions.
// Issue: https://github.com/unoplatform/uno/issues/2769
sutLayoutUpdate1.Should().Be(2, "sut-before");
sutLayoutUpdate2.Should().Be(4, "sut-after");
#elif UNO_HAS_ENHANCED_LIFECYCLE || WINAPPSDK
#if UNO_HAS_ENHANCED_LIFECYCLE || WINAPPSDK
sutLayoutUpdate1.Should().Be(0, "sut-1");
sutLayoutUpdate2.Should().Be(0, "sut-2");
sutLayoutUpdate3.Should().Be(0, "sut-3");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Top, 10, 0, false, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Top, 0, 10, false, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Top, 10, 10, false, false)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Top, 0, 0, false, false)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Top, 10, 0, false, false)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Top, 0, 10, false, false)]
Expand All @@ -757,7 +757,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Stretch, VerticalAlignment.Top, 10, 0, false, false)]
[DataRow(HorizontalAlignment.Stretch, VerticalAlignment.Top, 0, 10, false, false)]
[DataRow(HorizontalAlignment.Stretch, VerticalAlignment.Top, 10, 10, false, false)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 0, 0, false, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 10, 0, false, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 0, 10, false, false)]
Expand Down Expand Up @@ -795,7 +795,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Stretch, 10, 0, false, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Stretch, 0, 10, false, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Stretch, 10, 10, false, false)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Stretch, 0, 0, false, false)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Stretch, 10, 0, false, false)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Stretch, 0, 10, false, false)]
Expand Down Expand Up @@ -826,7 +826,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Stretch, VerticalAlignment.Top, 10, 0, true, false)]
[DataRow(HorizontalAlignment.Stretch, VerticalAlignment.Top, 0, 10, true, false)]
[DataRow(HorizontalAlignment.Stretch, VerticalAlignment.Top, 10, 10, true, false)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 0, 0, true, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 10, 0, true, false)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 0, 10, true, false)]
Expand Down Expand Up @@ -882,7 +882,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Top, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Top, 0, 10, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Top, 10, 10, false, true)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Top, 0, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Top, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Top, 0, 10, false, true)]
Expand All @@ -900,7 +900,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 0, 10, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Center, 10, 10, false, true)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Center, 0, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Center, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Center, 0, 10, false, true)]
Expand All @@ -918,7 +918,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Bottom, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Bottom, 0, 10, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Bottom, 10, 10, false, true)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Bottom, 0, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Bottom, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Bottom, 0, 10, false, true)]
Expand All @@ -936,7 +936,7 @@ public async Task When_PaddedElementInScrollViewer_Then_TransformToVisual(
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Stretch, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Stretch, 0, 10, false, true)]
[DataRow(HorizontalAlignment.Left, VerticalAlignment.Stretch, 10, 10, false, true)]
#if !__SKIA__ && !__WASM__
#if !__SKIA__ && !__WASM__ && !__ANDROID__
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Stretch, 0, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Stretch, 10, 0, false, true)]
[DataRow(HorizontalAlignment.Center, VerticalAlignment.Stretch, 0, 10, false, true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -938,11 +938,7 @@ public async Task When_InvalidatingMeasureExplicitly()

using var _ = new AssertionScope();

#if __ANDROID__
ctl1.MeasureCount.Should().Be(2);
#else
ctl1.MeasureCount.Should().Be(1);
#endif
ctl2.MeasureCount.Should().Be(2);
ctl3.MeasureCount.Should().Be(1);

Expand Down Expand Up @@ -1161,6 +1157,7 @@ private partial class MeasureAndArrangeCounter : Panel
{
internal int MeasureCount;
internal int ArrangeCount;

protected override Size MeasureOverride(Size availableSize)
{
MeasureCount++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,8 @@ public async Task When_Content_Set_Null_ComboBox()

contentControl.Content = null;

#if __IOS__ || __ANDROID__
Assert.AreEqual(0, comboBox.Items.Count);
Assert.AreEqual(-1, comboBox.SelectedIndex);
#else // this is correct
Assert.AreEqual(3, comboBox.Items.Count);
Assert.AreEqual(1, comboBox.SelectedIndex);
#endif
}

#if HAS_UNO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1103,11 +1103,7 @@ public void When_Grid_Has_Three_Element_With_ColSpan_and_Four_Progressing_Column

SUT.Arrange(new Rect(0, 0, 20, 20));

#if __ANDROID__ || __IOS__ || __MACOS__
c1.SizePassedToArrangeOverride.Should().Be(new Size(6, 10));
#else
c1.SizePassedToArrangeOverride.Should().Be(new Size(10, 10));
#endif
LayoutInformation.GetLayoutSlot(c1).Should().Be(new Rect(0, 0, 6, 10));

c2.SizePassedToArrangeOverride.Should().Be(new Size(10, 11));
Expand Down Expand Up @@ -1885,17 +1881,11 @@ public void When_One_Child_With_Margin_1234_Size8()
SUT.Measure(new Size(8, 8));

SUT.DesiredSize.Should().Be(new Size(8, 8));
#if UNO_REFERENCE_API
#if !WINAPPSDK
GetUnclippedDesiredSize(SUT).Should().Be(new Size(8, 8));
#elif !WINAPPSDK
GetUnclippedDesiredSize(SUT).Should().Be(new Size(8, 10));
#endif

#if UNO_REFERENCE_API
c1.DesiredSize.Should().Be(new Size(4, 4));
#else
c1.DesiredSize.Should().Be(new Size(4, 6));
#endif
#if !WINAPPSDK
GetUnclippedDesiredSize(c1).Should().Be(new Size(0, 0)); // UnclippedDesiredSize excludes margins
#endif
Expand All @@ -1908,11 +1898,7 @@ public void When_One_Child_With_Margin_1234_Size8()
c1.SizePassedToArrangeOverride.Should().Be(default);
c1.SizePassedToMeasureOverride.Should().Be(default);
LayoutInformation.GetAvailableSize(c1).Should().Be(new Size(4, 4));
#if UNO_REFERENCE_API || WINAPPSDK
LayoutInformation.GetLayoutSlot(c1).Should().Be(new Rect(2, 2, 4, 4));
#else
LayoutInformation.GetLayoutSlot(c1).Should().Be(new Rect(2, 2, 4, 6));
#endif

SUT.Children.Should().HaveCount(1);
}
Expand All @@ -1939,16 +1925,11 @@ public void When_One_Child_With_Margin_Center_And_Center()
SUT.Measure(new Size(20, 20));
SUT.DesiredSize.Should().Be(new Size(10, 20), because: "SUT.DesiredSize");

#if UNO_REFERENCE_API
#if !WINAPPSDK
GetUnclippedDesiredSize(SUT).Should().Be(new Size(10, 20), because: "SUT UnclippedDesiredSize");
#endif

#if UNO_REFERENCE_API || WINAPPSDK
c1.DesiredSize.Should().Be(new Size(10, 20), because: "c1.DesiredSize");
#else
GetUnclippedDesiredSize(SUT).Should().Be(new Size(10, 30), because: "SUT UnclippedDesiredSize");
c1.DesiredSize.Should().Be(new Size(10, 30), because: "c1.DesiredSize");
#endif

#if !WINAPPSDK
GetUnclippedDesiredSize(c1).Should().Be(new Size(10, 10), because: "c1 UnclippedDesiredSize"); // UnclippedDesiredSize excludes margins
Expand All @@ -1962,11 +1943,7 @@ public void When_One_Child_With_Margin_Center_And_Center()
c1.SizePassedToArrangeOverride.Should().Be(new Size(10, 10), because: "c1.SizePassedToArrangeOverride");
#endif

#if UNO_REFERENCE_API
c1.SizePassedToMeasureOverride.Should().Be(new Size(10, 10), because: "c1.SizePassedToMeasureOverride");
#else
c1.SizePassedToMeasureOverride.Should().Be(new Size(10, 0), because: "c1.SizePassedToMeasureOverride");
#endif
LayoutInformation.GetAvailableSize(c1).Should().Be(new Size(20, 20), because: "c1 AvailableSize");
LayoutInformation.GetLayoutSlot(c1).Should().Be(new Rect(0, 0, 50, 50), because: "c1 LayoutSlot");

Expand Down Expand Up @@ -1995,17 +1972,11 @@ public void When_One_Child_With_Margin_Center_And_Bottom()
SUT.Measure(new Size(20, 20));

SUT.DesiredSize.Should().Be(new Size(10, 20), because: "SUT.DesiredSize");
#if UNO_REFERENCE_API
#if !WINAPPSDK
GetUnclippedDesiredSize(SUT).Should().Be(new Size(10, 20), because: "SUT UnclippedDesiredSize");
#elif !WINAPPSDK
GetUnclippedDesiredSize(SUT).Should().Be(new Size(10, 30), because: "SUT.UnclippedDesiredSize");
#endif

#if UNO_REFERENCE_API || WINAPPSDK
c1.DesiredSize.Should().Be(new Size(10, 20), because: "c1.DesiredSize");
#else
c1.DesiredSize.Should().Be(new Size(10, 30), because: "c1.DesiredSize");
#endif

#if !WINAPPSDK
GetUnclippedDesiredSize(c1).Should().Be(new Size(10, 10), because: "c1 UnclippedDesiredSize"); // UnclippedDesiredSize excludes margins
Expand All @@ -2022,11 +1993,7 @@ public void When_One_Child_With_Margin_Center_And_Bottom()
c1.SizePassedToArrangeOverride.Should().Be(new Size(10, 10), because: "c1.SizePassedToArrangeOverride");
#endif

#if UNO_REFERENCE_API
c1.SizePassedToMeasureOverride.Should().Be(new Size(10, 10), because: "c1.SizePassedToMeasureOverride");
#else
c1.SizePassedToMeasureOverride.Should().Be(new Size(10, 0), because: "c1.SizePassedToMeasureOverride");
#endif
LayoutInformation.GetAvailableSize(c1).Should().Be(new Size(20, 20), because: "c1 AvailableSize");
LayoutInformation.GetLayoutSlot(c1).Should().Be(new Rect(0, 0, 50, 50), because: "c1 LayoutSlot");

Expand Down Expand Up @@ -2055,14 +2022,12 @@ public void When_One_Child_With_Margin_Center_And_Top()
SUT.Measure(new Size(20, 20));

SUT.DesiredSize.Should().Be(new Size(10, 20), because: "SUT.DesiredSize");
#if UNO_REFERENCE_API
#if !WINAPPSDK
GetUnclippedDesiredSize(SUT).Should().Be(new Size(10, 20), because: "SUT UnclippedDesiredSize");
c1.DesiredSize.Should().Be(new Size(10, 20), because: "c1.DesiredSize");
#elif !WINAPPSDK
GetUnclippedDesiredSize(SUT).Should().Be(new Size(10, 30), because: "SUT UnclippedDesiredSize");
c1.DesiredSize.Should().Be(new Size(10, 30), because: "c1.DesiredSize");
#endif

c1.DesiredSize.Should().Be(new Size(10, 20), because: "c1.DesiredSize");

#if !WINAPPSDK
GetUnclippedDesiredSize(c1).Should().Be(new Size(10, 10), because: "c1 UnclippedDesiredSize"); // UnclippedDesiredSize excludes margins
#endif
Expand All @@ -2075,11 +2040,7 @@ public void When_One_Child_With_Margin_Center_And_Top()
c1.SizePassedToArrangeOverride.Should().Be(new Size(10, 10), because: "c1.SizePassedToArrangeOverride");
#endif

#if UNO_REFERENCE_API
c1.SizePassedToMeasureOverride.Should().Be(new Size(10, 10), because: "c1.SizePassedToMeasureOverride");
#else
c1.SizePassedToMeasureOverride.Should().Be(new Size(10, 0), because: "c1.SizePassedToMeasureOverride");
#endif
LayoutInformation.GetAvailableSize(c1).Should().Be(new Size(20, 20), because: "c1 AvailableSize");
LayoutInformation.GetLayoutSlot(c1).Should().Be(new Rect(0, 0, 50, 50), because: "c1 LayoutSlot");

Expand Down Expand Up @@ -2133,13 +2094,7 @@ public void When_One_Fixed_Size_Child_With_Margin_Right_And_Stretch()
#if !WINAPPSDK
private static Size GetUnclippedDesiredSize(UIElement element)
{
#if UNO_REFERENCE_API
return element.m_unclippedDesiredSize;
#else
var layouterElement = (ILayouterElement)element;
var layouter = (Layouter)layouterElement.Layouter;
return layouter._unclippedDesiredSize;
#endif
}
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ public async Task When_Item_Margins()

[TestMethod]
[RunsOnUIThread]
#if __ANDROID__
[Ignore("Fails on WinUI similarly. It looks like an invalid test.")]
#endif
public async Task When_Item_Changes_Measure_Count()
{
var template = (DataTemplate)_testsResources["When_Item_Changes_Measure_Count_Template"];
Expand Down Expand Up @@ -324,7 +327,7 @@ public async Task When_Item_Recycled_DuringScroll()
{
// We should not throw/assert here, as this event is coming straight from native without any exception-guard.
// Throwing in this context will cause the app to crash directly.
snapshots.Add((previous.Index, previous.Container.ClippedFrame));
snapshots.Add((previous.Index, previous.Container.m_pLayoutClipGeometry));
}

previousContainer = (e.ItemIndex, (ListViewItem)e.ItemContainer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,24 +251,12 @@ private async Task MaxSizingTest(Size maxConstraints)

if (!double.IsInfinity(maxConstraints.Width))
{
#if WINAPPSDK || __CROSSRUNTIME__
Assert.AreEqual(constrained.ActualWidth, orientation == Orientation.Horizontal ? 1000 : maxConstraints.Width);
#else
// TODO: Align Uno with Windows behavior.
Assert.AreEqual(constrained.ActualWidth, maxConstraints.Width);
#endif

Assert.AreEqual(constrained.DesiredSize.Width, maxConstraints.Width);
}
if (!double.IsInfinity(maxConstraints.Height))
{
#if WINAPPSDK || __CROSSRUNTIME__
Assert.AreEqual(constrained.ActualHeight, orientation == Orientation.Vertical ? 1000 : maxConstraints.Height);
#else
// TODO: Align Uno with Windows behavior.
Assert.AreEqual(constrained.ActualHeight, maxConstraints.Height);
#endif

Assert.AreEqual(constrained.DesiredSize.Height, maxConstraints.Height);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,9 @@ public async Task When_Uri_Nullified()

var initialScreenshot = await UITestHelper.ScreenShot(border);

bitmapImage.UriSource = new Uri("ms-appx:///Assets/BlueSquare.png");
bool opened = false;
bitmapImage.ImageOpened += (s, e) => opened = true;
bitmapImage.UriSource = new Uri("ms-appx:///Assets/BlueSquare.png");

await WindowHelper.WaitForIdle();
await WindowHelper.WaitFor(() => opened);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,12 @@ public async Task When_Rectangle_Rounded_Measure_Height()
var nativeViewTopBorder = topBorder as Android.Views.View;
var nativeViewRect = rect as Android.Views.View;
var nativeViewBottomBorder = bottomBorder as Android.Views.View;
var nativeGrid = grid as Android.Views.View;

Assert.AreEqual(146, nativeViewTopBorder.Height);
Assert.AreEqual(147, nativeViewRect.Height);
Assert.AreEqual(146, nativeViewBottomBorder.Height);
Assert.AreEqual(nativeGrid.Height, nativeViewTopBorder.Height + nativeViewRect.Height + nativeViewBottomBorder.Height);

Assert.AreEqual(146, nativeViewRect.Top);
Assert.AreEqual(293, nativeViewRect.Bottom);
Assert.AreEqual(293, nativeViewBottomBorder.Top);

Assert.IsNotNull(rect.FrameRoundingAdjustment);
Assert.AreEqual(1, rect.FrameRoundingAdjustment.Value.Height);
Assert.AreEqual(0, rect.FrameRoundingAdjustment.Value.Width);
Assert.AreEqual(nativeViewRect.Top, nativeViewTopBorder.Bottom);
Assert.AreEqual(nativeViewBottomBorder.Top, nativeViewRect.Bottom);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/Behaviors/VisibleBoundsPadding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ internal VisibleBoundsDetails(FrameworkElement owner)

_originalPadding = owner.GetPadding();

_visibleBoundsChanged = (s2, e2) => UpdatePadding();
_visibleBoundsChanged = (s2, e2) => Owner?.InvalidateArrange();

#if __IOS__
// For iOS, it's required to react on SizeChanged to prevent weird alignment
Expand Down
Loading
Loading