diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs index 7e93d347b36e..9f0614452a26 100644 --- a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs +++ b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs @@ -559,11 +559,11 @@ void TearDownEmptyView() _emptyViewFormsElement = null; } - void LayoutEmptyView() + virtual internal CGRect LayoutEmptyView() { if (!_initialized || _emptyUIView == null || _emptyUIView.Superview == null) { - return; + return CGRect.Empty; } var frame = DetermineEmptyViewFrame(); @@ -572,6 +572,8 @@ void LayoutEmptyView() if (_emptyViewFormsElement != null && ((IElementController)ItemsView).LogicalChildren.IndexOf(_emptyViewFormsElement) != -1) _emptyViewFormsElement.Layout(frame.ToRectangle()); + + return frame; } internal protected virtual void UpdateVisibility() diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs index 4823dff0bbe6..3ece516b51a7 100644 --- a/src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs +++ b/src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs @@ -107,6 +107,9 @@ void UpdateDefaultSupplementaryView(DefaultCell2 cell, NSString elementKind) : ItemsView.Footer; cell.Label.Text = obj?.ToString(); + cell.Tag = elementKind == UICollectionElementKindSectionKey.Header + ? HeaderTag + : FooterTag; } void UpdateTemplatedSupplementaryView(TemplatedCell2 cell, NSString elementKind) @@ -160,6 +163,21 @@ string DetermineViewReuseId(DataTemplate template, object item) ? HorizontalSupplementaryView2.ReuseId : VerticalSupplementaryView2.ReuseId; } + internal override CGRect LayoutEmptyView() + { + var emptyViewFrame = base.LayoutEmptyView(); + var footerView = CollectionView.ViewWithTag(FooterTag); + + if (footerView is not null) + { + if (emptyViewFrame.Height > 0) + footerView.Frame = new CGRect(footerView.Frame.X, emptyViewFrame.Bottom, footerView.Frame.Width, footerView.Frame.Height); + else + footerView.Frame = new CGRect(footerView.Frame.X, CollectionView.ContentSize.Height - footerView.Frame.Height, footerView.Frame.Width, footerView.Frame.Height); + } + + return emptyViewFrame; + } protected override CGRect DetermineEmptyViewFrame() { @@ -175,8 +193,8 @@ protected override CGRect DetermineEmptyViewFrame() if (footerView != null) footerHeight = footerView.Frame.Height; - return new CGRect(CollectionView.Frame.X, CollectionView.Frame.Y, CollectionView.Frame.Width, - Math.Abs(CollectionView.Frame.Height - (headerHeight + footerHeight))); + return new CGRect(CollectionView.Frame.X, CollectionView.Frame.Y + headerHeight, CollectionView.Frame.Width, + Math.Abs(CollectionView.Frame.Height - (headerHeight + footerHeight))); } public override void ViewWillLayoutSubviews() diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue28604.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue28604.cs new file mode 100644 index 000000000000..f7bfdb182f97 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue28604.cs @@ -0,0 +1,61 @@ +using System.Collections.ObjectModel; + +namespace Maui.Controls.Sample.Issues; +[Issue(IssueTracker.Github, 28604, "Footer Not Displayed at the Bottom When EmptyView is Active in CV2", PlatformAffected.iOS)] +public class Issue28604 : ContentPage +{ + private CollectionViewViewModel ViewModel; + + public Issue28604() + { + ViewModel = new CollectionViewViewModel(); + BindingContext = ViewModel; + + var grid = new Grid(); + + var collectionView = new CollectionView2 + { + AutomationId = "CollectionView", + ItemsSource = ViewModel.ItemList, + EmptyView = "EmptyView", + Background = Colors.AliceBlue, + Header = new VerticalStackLayout + { + BackgroundColor = Colors.Red, + Children = + { + new Label + { + Text = "Header", + FontAttributes = FontAttributes.Bold + } + } + }, + Footer = new VerticalStackLayout + { + BackgroundColor = Colors.Yellow, + Children = + { + new Label + { + Text = "Footer", + FontAttributes = FontAttributes.Bold + } + } + } + }; + grid.Children.Add(collectionView); + + Content = grid; + } +} + +public class CollectionViewViewModel +{ + public ObservableCollection ItemList { get; set; } + + public CollectionViewViewModel() + { + ItemList = new ObservableCollection(); + } +} diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FooterShouldDisplayAtBottomOfEmptyView.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FooterShouldDisplayAtBottomOfEmptyView.png new file mode 100644 index 000000000000..6172aad7c1d9 Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FooterShouldDisplayAtBottomOfEmptyView.png differ diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28604.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28604.cs new file mode 100644 index 000000000000..9ca4dbf12484 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28604.cs @@ -0,0 +1,23 @@ +#if !ANDROID // this test case is ignored in android, as it has incositent scrolling behavior while using emptyView as string. https://github.com/dotnet/maui/issues/28765 +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue28604 : _IssuesUITest +{ + public Issue28604(TestDevice testDevice) : base(testDevice) + { + } + public override string Issue => "Footer Not Displayed at the Bottom When EmptyView is Active in CV2"; + + [Test] + [Category(UITestCategories.CollectionView)] + public void FooterShouldDisplayAtBottomOfEmptyView() + { + App.WaitForElement("CollectionView"); + VerifyScreenshot(); + } +} +#endif \ No newline at end of file diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/FooterShouldDisplayAtBottomOfEmptyView.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/FooterShouldDisplayAtBottomOfEmptyView.png new file mode 100644 index 000000000000..6e6f45e88327 Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/FooterShouldDisplayAtBottomOfEmptyView.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FooterShouldDisplayAtBottomOfEmptyView.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FooterShouldDisplayAtBottomOfEmptyView.png new file mode 100644 index 000000000000..5f78fb9e81f8 Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FooterShouldDisplayAtBottomOfEmptyView.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/HeaderAndFooterShouldBeVisible.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/HeaderAndFooterShouldBeVisible.png index 6bf34ccfb909..f57254fe934f 100644 Binary files a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/HeaderAndFooterShouldBeVisible.png and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/HeaderAndFooterShouldBeVisible.png differ