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

[ios,tests] Fix iOS Header with Group #25157

Merged
merged 13 commits into from
Oct 22, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -105,15 +115,26 @@ 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()
{
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();
Expand Down Expand Up @@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ protected override UICollectionViewLayout SelectLayout()
{
headerFooterInfo.FooterView = footerView;
}
headerFooterInfo.HasHeader = structuredItemsView.Header is not null;
headerFooterInfo.HasFooter = structuredItemsView.Footer is not null;
headerFooterInfo.HasHeader = structuredItemsView.Header is not null || structuredItemsView.HeaderTemplate is not null;
headerFooterInfo.HasFooter = structuredItemsView.Footer is not null || structuredItemsView.FooterTemplate is not null;
}

var itemSizingStrategy = ItemsView.ItemSizingStrategy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ protected override void RegisterViewTypes()

private protected override void RegisterSupplementaryViews(UICollectionElementKindSection kind)
{
base.RegisterSupplementaryViews(kind);
if (IsHorizontal)
base.RegisterSupplementaryViews(kind);
if (IsHorizontal)
{
CollectionView.RegisterClassForSupplementaryView(typeof(HorizontalSupplementaryView2),
kind, HorizontalSupplementalView2ReuseId);
Expand All @@ -87,10 +87,15 @@ string DetermineViewReuseId(NSString elementKind)
public override UICollectionReusableView GetViewForSupplementaryElement(UICollectionView collectionView,
NSString elementKind, NSIndexPath indexPath)
{
var suplementaryViewFromStructuredView = base.GetViewForSupplementaryElement(collectionView, elementKind, indexPath);
if (suplementaryViewFromStructuredView is not null)
// If the IndexPath is less than 2, it's a header or footer for a section not a group
if (indexPath.Length < 2 || (ItemsView.GroupFooterTemplate is null && ItemsView.GroupHeaderTemplate is null))
{
return suplementaryViewFromStructuredView;

var suplementaryViewFromStructuredView = base.GetViewForSupplementaryElement(collectionView, elementKind, indexPath);
if (suplementaryViewFromStructuredView is not null)
{
return suplementaryViewFromStructuredView;
}
}

var reuseId = DetermineViewReuseId(elementKind);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,14 +401,13 @@ protected virtual CGRect DetermineEmptyViewFrame()
internal void UpdateView(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
{
// Is view set on the ItemsView?
if (view == null)
if (view == null && viewTemplate is null)
{
if (formsElement != null)
{
//Platform.GetRenderer(formsElement)?.DisposeRendererAndChildren();
}


uiView?.Dispose();
uiView = null;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Controls.Sample.UITests;
using Maui.Controls.Sample.CollectionViewGalleries.GroupingGalleries;
using Maui.Controls.Sample.CollectionViewGalleries.HeaderFooterGalleries;
using Maui.Controls.Sample.CollectionViewGalleries.ItemSizeGalleries;
using Maui.Controls.Sample.CollectionViewGalleries.SelectionGalleries;

Expand Down Expand Up @@ -35,6 +37,8 @@ public CollectionViewCoreGalleryContentPage()
// VisitAndUpdateItemsSource (src\Compatibility\ControlGallery\src\UITests.Shared\Tests\CollectionViewUITests.cs)
TestBuilder.NavButton("Default Text Galleries", () => new DefaultTextGallery(), Navigation),
TestBuilder.NavButton("DataTemplate Galleries", () => new DataTemplateGallery(), Navigation),
TestBuilder.NavButton("Grouping Galleries", () => new GroupingGallery(), Navigation),
TestBuilder.NavButton("Header Footer Galleries", () => new HeaderFooterGallery(), Navigation),
TestBuilder.NavButton("Observable Collection Galleries", () => new ObservableCollectionGallery(), Navigation),
// SelectionShouldUpdateBinding (src\Compatibility\ControlGallery\src\Issues.Shared\CollectionViewBoundSingleSelection.cs)
// ItemsFromViewModelShouldBeSelected (src\Compatibility\ControlGallery\src\Issues.Shared\CollectionViewBoundMultiSelection.cs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class HeaderFooterDemoModel : INotifyPropertyChanged

public HeaderFooterDemoModel()
{
CurrentTime = DateTime.Now;
CurrentTime = new DateTime(2023,1,1);
}

void OnPropertyChanged([CallerMemberName] string property = "")
Expand All @@ -36,7 +36,7 @@ void OnPropertyChanged([CallerMemberName] string property = "")

public ObservableCollection<CollectionViewGalleryTestItem> Items => _demoFilteredItemSource.Items;

public ICommand TapCommand => new Command(() => { CurrentTime = DateTime.Now; });
public ICommand TapCommand => new Command(() => { CurrentTime = new DateTime(2024,1,1); });

public DateTime CurrentTime
{
Expand Down
44 changes: 44 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue20443.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?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="Controls.TestCases.HostApp.Issues.Issue20443"
xmlns:local="clr-namespace:Controls.TestCases.HostApp.Issues"
x:DataType="local:Issue20443ViewModel"
Title="Issue20443">
<ContentPage.BindingContext>
<local:Issue20443ViewModel/>
</ContentPage.BindingContext>
<Grid>
<RefreshView
IsRefreshing="{Binding IsRefreshing}"
Command="{Binding RefreshCommand}">
<CollectionView
ItemSizingStrategy="MeasureAllItems"
ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<local:Issue20443TemplateSelector>
<local:Issue20443TemplateSelector.ItemATemplate>
<DataTemplate>
<Grid
HeightRequest="20"
BackgroundColor="Aqua">
<Label Text="20"/>
</Grid>
</DataTemplate>
</local:Issue20443TemplateSelector.ItemATemplate>
<local:Issue20443TemplateSelector.ItemBTemplate>
<DataTemplate>
<Grid
HeightRequest="100"
BackgroundColor="Pink">
<Label Text="100"/>
</Grid>
</DataTemplate>
</local:Issue20443TemplateSelector.ItemBTemplate>
</local:Issue20443TemplateSelector>
</CollectionView.ItemTemplate>

</CollectionView>
</RefreshView>
</Grid>
</ContentPage>
90 changes: 90 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue20443.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;
using System.Runtime.CompilerServices;

namespace Controls.TestCases.HostApp.Issues
{
[Issue(IssueTracker.Github, 20443, "CollectionView item gets wrong size after refresh", PlatformAffected.iOS)]

public partial class Issue20443 : ContentPage
{
public Issue20443()
{
InitializeComponent();
}
}
public class Issue20443ViewModel : INotifyPropertyChanged
{
public IList<object> Items { get; set; }

private bool _isRefreshing;

public bool IsRefreshing
{
get => _isRefreshing;
set
{
_isRefreshing = value;
OnPropertyChanged();
}
}

public Command RefreshCommand { get; set; }

public Issue20443ViewModel()
{
RefreshCommand = new Command(
async () =>
{
await Task.Delay(2000);
IsRefreshing = false;
});

Items = new List<object>();
for (int i = 0; i < 100; i++)
{
Items.Add(new Issue20443ItemA());
Items.Add(new Issue20443ItemB());
Items.Add(new Issue20443ItemB());
Items.Add(new Issue20443ItemB());
Items.Add(new Issue20443ItemB());
}
}

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

public class Issue20443ItemA
{

}

public class Issue20443ItemB
{

}

public class Issue20443TemplateSelector : DataTemplateSelector
{
public DataTemplate ItemATemplate { get; set; }
public DataTemplate ItemBTemplate { get; set; }

protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is Issue20443ItemA)
{
return ItemATemplate;
}

return ItemBTemplate;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests
{
#if IOS
public class CollectionViewGroupingTests : CollectionViewUITests
{
protected override bool ResetAfterEachTest => true;

public CollectionViewGroupingTests(TestDevice device)
: base(device)
{
}

[Test]
[Category(UITestCategories.CollectionView)]
public void GroupingAndHeaderWorks()
{
VisitInitialGallery("Grouping");

VisitSubGallery("Basic Grouping");

// header
App.WaitForElement("This is a header");
// group header
App.WaitForElement("Avengers");
// group footer
App.WaitForElement("Total members: 12");
}
}
#endif
}
Loading
Loading