Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@ void UpdateHeaderFooterPosition()

if (_headerUIView != null && _headerUIView.Frame.X != -headerWidth)
{
_headerUIView.Frame = new CGRect(-headerWidth, 0, headerWidth, CollectionView.Frame.Height);
// Use the actual measured height of the header view instead of the full CollectionView height
nfloat headerHeight = _headerUIView.Frame.Height;
_headerUIView.Frame = new CGRect(-headerWidth, 0, headerWidth, headerHeight);
}

if (_footerUIView != null && IsViewLoaded && View.Window != null)
Expand All @@ -167,7 +169,9 @@ void UpdateHeaderFooterPosition()

if (currentFrame.X != footerX)
{
_footerUIView.Frame = new CGRect(footerX, 0, footerWidth, CollectionView.Frame.Height);
// Use the actual measured height of the footer view instead of the full CollectionView height
nfloat footerHeight = _footerUIView.Frame.Height;
_footerUIView.Frame = new CGRect(footerX, 0, footerWidth, footerHeight);
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ public static UICollectionViewLayout CreateGrid(GridItemsLayout gridItemsLayout,
static NSCollectionLayoutBoundarySupplementaryItem[] CreateSupplementaryItems(LayoutGroupingInfo? groupingInfo, LayoutHeaderFooterInfo? layoutHeaderFooterInfo,
UICollectionViewScrollDirection scrollDirection, NSCollectionLayoutDimension width, NSCollectionLayoutDimension height)
{
// For horizontal layouts, use estimated dimensions for headers/footers instead of full group height
// This prevents headers/footers from being cropped when group height is fractional (full height)
var headerFooterWidth = scrollDirection == UICollectionViewScrollDirection.Horizontal ? NSCollectionLayoutDimension.CreateEstimated(30f) : width;
var headerFooterHeight = scrollDirection == UICollectionViewScrollDirection.Horizontal ? NSCollectionLayoutDimension.CreateEstimated(30f) : height;

if (groupingInfo is not null && groupingInfo.IsGrouped)
{
var items = new List<NSCollectionLayoutBoundarySupplementaryItem>();

if (groupingInfo.HasHeader)
{
items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create(
NSCollectionLayoutSize.Create(width, height),
NSCollectionLayoutSize.Create(headerFooterWidth, headerFooterHeight),
UICollectionElementKindSectionKey.Header.ToString(),
scrollDirection == UICollectionViewScrollDirection.Vertical
? NSRectAlignment.Top
Expand All @@ -42,7 +47,7 @@ static NSCollectionLayoutBoundarySupplementaryItem[] CreateSupplementaryItems(La
if (groupingInfo.HasFooter)
{
items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create(
NSCollectionLayoutSize.Create(width, height),
NSCollectionLayoutSize.Create(headerFooterWidth, headerFooterHeight),
UICollectionElementKindSectionKey.Footer.ToString(),
scrollDirection == UICollectionViewScrollDirection.Vertical
? NSRectAlignment.Bottom
Expand All @@ -59,7 +64,7 @@ static NSCollectionLayoutBoundarySupplementaryItem[] CreateSupplementaryItems(La
if (layoutHeaderFooterInfo.HasHeader)
{
items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create(
NSCollectionLayoutSize.Create(width, height),
NSCollectionLayoutSize.Create(headerFooterWidth, headerFooterHeight),
UICollectionElementKindSectionKey.Header.ToString(),
scrollDirection == UICollectionViewScrollDirection.Vertical
? NSRectAlignment.Top
Expand All @@ -70,7 +75,7 @@ static NSCollectionLayoutBoundarySupplementaryItem[] CreateSupplementaryItems(La
if (layoutHeaderFooterInfo.HasFooter)
{
items.Add(NSCollectionLayoutBoundarySupplementaryItem.Create(
NSCollectionLayoutSize.Create(width, height),
NSCollectionLayoutSize.Create(headerFooterWidth, headerFooterHeight),
UICollectionElementKindSectionKey.Footer.ToString(),
scrollDirection == UICollectionViewScrollDirection.Vertical
? NSRectAlignment.Bottom
Expand Down
80 changes: 80 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue26835.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue26835"
Title="Issue 26835">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Label Grid.Row="0"
Text="Horizontal Grid CollectionView with Header/Footer - Should show full header and footer without cropping"
FontSize="16"
Margin="10" />

<CollectionView Grid.Row="1"
x:Name="CollectionView"
AutomationId="HorizontalGridCollectionView"
BackgroundColor="LightGray">

<CollectionView.ItemsLayout>
<GridItemsLayout Span="3"
Orientation="Horizontal"
HorizontalItemSpacing="5"
VerticalItemSpacing="5" />
</CollectionView.ItemsLayout>

<CollectionView.Header>
<StackLayout BackgroundColor="Blue" Padding="10" AutomationId="CollectionViewHeader">
<Label Text="HEADER CONTENT"
TextColor="White"
FontSize="18"
FontAttributes="Bold"
HorizontalOptions="Center"
AutomationId="HeaderTitle" />
<Label Text="This header should be fully visible"
TextColor="White"
HorizontalOptions="Center"
AutomationId="HeaderSubtitle" />
<Label Text="Line 3 of header content"
TextColor="White"
HorizontalOptions="Center"
AutomationId="HeaderLine3" />
</StackLayout>
</CollectionView.Header>

<CollectionView.Footer>
<StackLayout BackgroundColor="Red" Padding="10" AutomationId="CollectionViewFooter">
<Label Text="FOOTER CONTENT"
TextColor="White"
FontSize="18"
FontAttributes="Bold"
HorizontalOptions="Center"
AutomationId="FooterTitle" />
<Label Text="This footer should be fully visible"
TextColor="White"
HorizontalOptions="Center"
AutomationId="FooterSubtitle" />
<Label Text="Line 3 of footer content"
TextColor="White"
HorizontalOptions="Center"
AutomationId="FooterLine3" />
</StackLayout>
</CollectionView.Footer>

<CollectionView.ItemTemplate>
<DataTemplate>
<Grid BackgroundColor="LightBlue" HeightRequest="80" WidthRequest="80">
<Label Text="{Binding .}"
HorizontalOptions="Center"
VerticalOptions="Center"
FontSize="14" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>

</CollectionView>
</Grid>
</ContentPage>
29 changes: 29 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue26835.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Collections.ObjectModel;
using Microsoft.Maui.Controls;

namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 26835, "[iOS & Mac] Headers and Footers Get Cropped in CollectionView with Horizontal Grid and Horizontal Orientation",
PlatformAffected.iOS | PlatformAffected.macOS)]
public partial class Issue26835 : ContentPage
{
public ObservableCollection<string> Items { get; set; }

public Issue26835()
{
InitializeComponent();

// Create test data with enough items to demonstrate horizontal scrolling
Items = new ObservableCollection<string>();
for (int i = 1; i <= 30; i++)
{
Items.Add($"Item {i}");
}

CollectionView.ItemsSource = Items;

// Additional verification: Set AutomationIds for testing
CollectionView.AutomationId = "HorizontalGridCollectionView";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue26835 : _IssuesUITest
{
public Issue26835(TestDevice device) : base(device) { }

public override string Issue => "[iOS & Mac] Headers and Footers Get Cropped in CollectionView with Horizontal Grid and Horizontal Orientation";

[Test]
[Category(UITestCategories.CollectionView)]
public void HeaderAndFooterShouldNotBeCroppedInHorizontalGrid()
{
// Verify the CollectionView is present
App.WaitForElement("HorizontalGridCollectionView");

// Verify header elements are visible and not cropped
App.WaitForElement("HeaderTitle");
App.WaitForElement("HeaderSubtitle");
App.WaitForElement("HeaderLine3");

// Scroll to the right to reveal the footer at the end of the collection
for (int i = 0; i < 8; i++)
{
App.ScrollRight("HorizontalGridCollectionView", ScrollStrategy.Auto, 0.8, 500);
}

// Verify footer elements are visible and not cropped
App.WaitForElement("FooterTitle");
App.WaitForElement("FooterSubtitle");
App.WaitForElement("FooterLine3");

// Scroll back to verify header is still visible
for (int i = 0; i < 8; i++)
{
App.ScrollLeft("HorizontalGridCollectionView", ScrollStrategy.Auto, 0.8, 500);
}

// Verify header is still visible after scrolling
App.WaitForElement("HeaderTitle");
App.WaitForElement("HeaderSubtitle");
App.WaitForElement("HeaderLine3");
}
}
}