diff --git a/src/Controls/src/Core/Handlers/Items/iOS/StructuredItemsViewController.cs b/src/Controls/src/Core/Handlers/Items/iOS/StructuredItemsViewController.cs
index 62116b468264..a22a10b66475 100644
--- a/src/Controls/src/Core/Handlers/Items/iOS/StructuredItemsViewController.cs
+++ b/src/Controls/src/Core/Handlers/Items/iOS/StructuredItemsViewController.cs
@@ -46,6 +46,16 @@ protected override void Dispose(bool disposing)
_footerViewFormsElement.MeasureInvalidated -= OnFormsElementMeasureInvalidated;
}
+ if (_headerUIView is MauiView hv)
+ {
+ hv.LayoutChanged -= HeaderViewLayoutChanged;
+ }
+
+ if (_footerUIView is MauiView fv)
+ {
+ fv.LayoutChanged -= FooterViewLayoutChanged;
+ }
+
_headerUIView = null;
_headerViewFormsElement = null;
_footerUIView = null;
@@ -105,6 +115,11 @@ internal void UpdateFooterView()
UpdateSubview(ItemsView?.Footer, ItemsView?.FooterTemplate, FooterTag,
ref _footerUIView, ref _footerViewFormsElement);
UpdateHeaderFooterPosition();
+
+ if (_footerUIView is MauiView mv)
+ {
+ mv.LayoutChanged += FooterViewLayoutChanged;
+ }
}
internal void UpdateHeaderView()
@@ -112,8 +127,14 @@ internal void UpdateHeaderView()
UpdateSubview(ItemsView?.Header, ItemsView?.HeaderTemplate, HeaderTag,
ref _headerUIView, ref _headerViewFormsElement);
UpdateHeaderFooterPosition();
+
+ if(_headerUIView is MauiView mv)
+ {
+ mv.LayoutChanged += HeaderViewLayoutChanged;
+ }
}
+
internal void UpdateSubview(object view, DataTemplate viewTemplate, nint viewTag, ref UIView uiView, ref VisualElement formsElement)
{
uiView?.RemoveFromSuperview();
@@ -239,5 +260,15 @@ internal void UpdateLayoutMeasurements()
if (_footerViewFormsElement != null)
HandleFormsElementMeasureInvalidated(_footerViewFormsElement);
}
+
+ void HeaderViewLayoutChanged(object sender, EventArgs e)
+ {
+ HandleFormsElementMeasureInvalidated(_headerViewFormsElement);
+ }
+
+ void FooterViewLayoutChanged(object sender, EventArgs e)
+ {
+ HandleFormsElementMeasureInvalidated(_footerViewFormsElement);
+ }
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/HeaderShouldNotCollapseWithItems.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/HeaderShouldNotCollapseWithItems.png
new file mode 100644
index 000000000000..02de2114edb5
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/HeaderShouldNotCollapseWithItems.png differ
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue12429.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue12429.xaml
new file mode 100644
index 000000000000..ea45f56269e1
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue12429.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue12429.xaml.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue12429.xaml.cs
new file mode 100644
index 000000000000..2555713efdcf
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue12429.xaml.cs
@@ -0,0 +1,24 @@
+using System.Collections.ObjectModel;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Xaml;
+
+namespace Maui.Controls.Sample.Issues;
+
+[XamlCompilation(XamlCompilationOptions.Compile)]
+[Issue(IssueTracker.Github, 12429, "[iOS] CollectionView Items display issue when Header is resized", PlatformAffected.iOS)]
+
+public partial class Issue12429 : ContentPage
+{
+ public ObservableCollection ItemList { get; }
+ public ObservableCollection ItemListHeader { get; }
+
+ public Command AddCommand => new(() => ItemListHeader.Add($"HeaderItem{ItemListHeader.Count + 1}"));
+
+ public Issue12429()
+ {
+ InitializeComponent();
+ ItemList = new() { "Item1", "Item2", "Itme3" };
+ ItemListHeader = new() { "HeaderItem1" };
+ BindingContext = this;
+ }
+}
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue12429.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue12429.cs
new file mode 100644
index 000000000000..3e007a5a5f7c
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue12429.cs
@@ -0,0 +1,28 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+
+public class Issue12429 : _IssuesUITest
+{
+ public override string Issue => "[iOS] CollectionView Items display issue when Header is resized";
+
+ public Issue12429(TestDevice device) : base(device)
+ { }
+
+ [Test]
+ [Category(UITestCategories.CollectionView)]
+ public async Task HeaderShouldNotCollapseWithItems()
+ {
+ App.WaitForElement("button");
+ App.Click("button");
+ App.Click("button");
+ App.Click("button");
+
+ await Task.Delay(500);
+
+ //The test passes of header has 4 elements that don't overlap with the collection view's items
+ VerifyScreenshot();
+ }
+}
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/HeaderShouldNotCollapseWithItems.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/HeaderShouldNotCollapseWithItems.png
new file mode 100644
index 000000000000..6b3379e5dea0
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/HeaderShouldNotCollapseWithItems.png differ
diff --git a/src/Controls/tests/UITests/snapshots/windows/HeaderShouldNotCollapseWithItems.png b/src/Controls/tests/UITests/snapshots/windows/HeaderShouldNotCollapseWithItems.png
new file mode 100644
index 000000000000..b90d317ccac4
Binary files /dev/null and b/src/Controls/tests/UITests/snapshots/windows/HeaderShouldNotCollapseWithItems.png differ
diff --git a/src/Core/src/Platform/iOS/MauiView.cs b/src/Core/src/Platform/iOS/MauiView.cs
index c2d04b68e4e6..73ae21ffdcc7 100644
--- a/src/Core/src/Platform/iOS/MauiView.cs
+++ b/src/Core/src/Platform/iOS/MauiView.cs
@@ -137,6 +137,7 @@ public override void LayoutSubviews()
}
CrossPlatformArrange(bounds);
+ LayoutChanged?.Invoke(this, EventArgs.Empty);
}
public override void SetNeedsLayout()
@@ -198,5 +199,8 @@ public override void MovedToWindow()
_movedToWindow?.Invoke(this, EventArgs.Empty);
TryToInvalidateSuperView(true);
}
+
+ [UnconditionalSuppressMessage("Memory", "MEM0001", Justification = IUIViewLifeCycleEvents.UnconditionalSuppressMessage)]
+ internal event EventHandler? LayoutChanged;
}
}