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

Expander CollectionView GridLayout 1557 #1567

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,33 @@
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

<CollectionView ItemsSource="{Binding ContentCreators}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="4"
HorizontalItemSpacing="5"
VerticalItemSpacing="5" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<mct:Expander x:DataType="viewModels:ContentCreator"
ExpandedChanged="Expander_ExpandedChanged">
<mct:Expander.Header>
<Label Text="{Binding Name}"/>
</mct:Expander.Header>
<mct:Expander.Content>
<VerticalStackLayout>
<Label Text="{Binding Resource}" HorizontalOptions="Center"/>
<Image Source="{Binding Image}"
WidthRequest="100"
HeightRequest="100"/>
</VerticalStackLayout>
</mct:Expander.Content>
</mct:Expander>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>
</pages:BasePage>
102 changes: 77 additions & 25 deletions src/CommunityToolkit.Maui/Views/Expander/Expander.macios.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Reflection;
using CoreGraphics;
using Microsoft.Maui.Controls.Handlers.Items;
using UIKit;

namespace CommunityToolkit.Maui.Views;
Expand All @@ -15,41 +15,93 @@ static void ForceUpdateCellSize(CollectionView collectionView, Size size, Point?

var controller = GetController(collectionView);

if (controller?.CollectionView.CollectionViewLayout is UICollectionViewFlowLayout layout)
if (controller?.CollectionView.CollectionViewLayout is ListViewLayout listViewLayout)
{
var cells = layout.CollectionView.VisibleCells.OrderBy(x => x.Frame.Y).ToArray();
var clickedCell = GetCellByPoint(cells, new CGPoint(tapLocation.Value.X, tapLocation.Value.Y));
if (clickedCell is null)
{
return;
}

for (int i = 0; i < cells.Length; i++)
{
var cell = cells[i];

if (i > 0)
{
var prevCellFrame = cells[i - 1].Frame;
cell.Frame = new CGRect(cell.Frame.X, prevCellFrame.Y + prevCellFrame.Height, cell.Frame.Width, cell.Frame.Height);
}

if (cell.Equals(clickedCell))
{
cell.Frame = new CGRect(cell.Frame.X, cell.Frame.Y, cell.Frame.Width, size.Height);
}
}
UpdateListLayout(listViewLayout, tapLocation.Value, size);
}
else if (controller?.CollectionView.CollectionViewLayout is GridViewLayout gridViewLayout)
{
UpdateGridLayout(collectionView, gridViewLayout, tapLocation.Value, size);
}
}

static UICollectionViewController? GetController(CollectionView collectionView)
{
var handler = collectionView.Handler as Microsoft.Maui.Controls.Handlers.Items.CollectionViewHandler;
var handler = collectionView.Handler as CollectionViewHandler;
return handler?.Controller;
}

static UICollectionViewCell? GetCellByPoint(UICollectionViewCell[] cells, CGPoint point)
{
return cells.FirstOrDefault(cell => cell.Frame.Contains(point));
}

static void UpdateListLayout(UICollectionViewLayout layout, Point tapLocation, Size size)
{
var cells = layout.CollectionView.VisibleCells.OrderBy(x => x.Frame.Y).ToArray();
var clickedCell = GetCellByPoint(cells, new CGPoint(tapLocation.X, tapLocation.Y));
if (clickedCell is null)
{
return;
}

for (int i = 0; i < cells.Length; i++)
{
var cell = cells[i];

if (i > 0)
{
var prevCellFrame = cells[i - 1].Frame;
cell.Frame = new CGRect(cell.Frame.X, prevCellFrame.Y + prevCellFrame.Height, cell.Frame.Width, cell.Frame.Height);
}

if (cell.Equals(clickedCell))
{
cell.Frame = new CGRect(cell.Frame.X, cell.Frame.Y, cell.Frame.Width, size.Height);
}
}
}

static void UpdateGridLayout(CollectionView gridView, GridViewLayout gridViewLayout, Point tapLocation, Size size)
{
var numberOfColumns = ((GridItemsLayout)gridView.ItemsLayout).Span;
if (numberOfColumns == 0)
{
return;
}

var cells = gridViewLayout.CollectionView.VisibleCells.OrderBy(x => x.Frame.Y).ThenBy(x=>x.Frame.X).ToArray();
var clickedCell = GetCellByPoint(cells, new CGPoint(tapLocation.X, tapLocation.Y));
if (clickedCell is null)
{
return;
}

for (int i = 0; i < cells.Length; i++)
{
var cell = cells[i];
if (cell.Equals(clickedCell))
{
IterateItemsInRow(cells, i, numberOfColumns, size.Height);
}
}
}

static void IterateItemsInRow(IReadOnlyList<UICollectionViewCell> cells, int itemIndex, int totalColumns, double height)
{
var rowToIterate = itemIndex / totalColumns;
var startIndex = rowToIterate * totalColumns;

double y = 0;
for (var i = startIndex; i < startIndex + totalColumns; i++)
{
var cell = cells[i];
if (i == startIndex)
{
y = cell.Frame.Y;
}

cell.Frame = new CGRect(cell.Frame.X, y, cell.Frame.Width, height);
}
}
}
44 changes: 43 additions & 1 deletion src/CommunityToolkit.Maui/Views/Expander/Expander.windows.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using CommunityToolkit.Maui.Core.Extensions;
using Microsoft.Maui.Controls.Platform;
using Microsoft.UI.Xaml.Controls;

Expand Down Expand Up @@ -30,5 +29,48 @@ static void ForceUpdateCellSize(CollectionView collectionView, Size size, Point?
}
}
}
else if (collectionView.Handler?.PlatformView is FormsGridView gridView)
{
var numberOfColumns = gridView.Span;
if (numberOfColumns == 0)
{
return;
}

for (var i = 0; i < gridView.Items.Count; i++)
{
if (gridView.ContainerFromIndex(i) is GridViewItem gridViewItem)
{
var itemTransform = gridViewItem.TransformToVisual(gridView);
var itemPosition = itemTransform.TransformPoint(new Windows.Foundation.Point(0, 0));
var itemBounds = new Rect(itemPosition.X, itemPosition.Y, gridViewItem.ActualWidth, gridViewItem.ActualHeight);

if (itemBounds.Contains(tapLocation.Value))
{
IterateItemsInRow(gridView, i, numberOfColumns, size.Height);
break;
}
}
}
}
}

static void IterateItemsInRow(ItemsControl gridView, int itemIndex, int totalColumns, double height)
{
var rowToIterate = itemIndex / totalColumns;
var startIndex = rowToIterate * totalColumns;

for (var i = startIndex; i < startIndex + totalColumns; i++)
{
if (i >= gridView.Items.Count)
{
break;
}

if (gridView.ContainerFromIndex(i) is GridViewItem cell)
{
cell.Height = height + Random.Shared.NextDouble();
}
}
}
}