Skip to content
Merged
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 @@ -32,7 +32,10 @@ public override void ConstrainTo(CGSize constraint)

public override CGSize Measure()
{
return new CGSize(_constraint.Width, _constraint.Height);
// Go through the measure pass even if the constraints are fixed
// to ensure arrange pass has the appropriate desired size in place.
PlatformHandler.VirtualView.Measure(_constraint.Width, _constraint.Height);
return _constraint;
}

protected override (bool, Size) NeedsContentSizeUpdate(Size currentSize)
Expand All @@ -42,7 +45,7 @@ protected override (bool, Size) NeedsContentSizeUpdate(Size currentSize)

protected override bool AttributesConsistentWithConstrainedDimension(UICollectionViewLayoutAttributes attributes)
{
return false;
return _constraint.IsCloseTo(attributes.Frame.Size);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ protected override string DetermineCellReuseId(NSIndexPath indexPath)
return base.DetermineCellReuseId(NSIndexPath.FromItemSection(itemIndex, 0));
}

private protected override (Type CellType, string CellTypeReuseId) DetermineTemplatedCellType()
=> (typeof(CarouselTemplatedCell), "maui_carousel");

protected override void RegisterViewTypes()
{
CollectionView.RegisterClassForCell(typeof(CarouselTemplatedCell), CarouselTemplatedCell.ReuseId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,9 @@ protected virtual string DetermineCellReuseId(NSIndexPath indexPath)
var dataTemplate = ItemsView.ItemTemplate.SelectDataTemplate(item, ItemsView);

var cellOrientation = ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Vertical ? "v" : "h";
var cellType = ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Vertical ? typeof(VerticalCell) : typeof(HorizontalCell);
(Type cellType, var cellTypeReuseId) = DetermineTemplatedCellType();

var reuseId = $"_maui_{cellOrientation}_{dataTemplate.Id}";
var reuseId = $"_{cellTypeReuseId}_{cellOrientation}_{dataTemplate.Id}";

if (!_cellReuseIds.Contains(reuseId))
{
Expand All @@ -521,6 +521,11 @@ protected virtual string DetermineCellReuseId(NSIndexPath indexPath)
: VerticalDefaultCell.ReuseId;
}

private protected virtual (Type CellType, string CellTypeReuseId) DetermineTemplatedCellType()
{
return (ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Vertical ? typeof(VerticalCell) : typeof(HorizontalCell), "maui");
}

[Obsolete("Use DetermineCellReuseId(NSIndexPath indexPath) instead.")]
protected virtual string DetermineCellReuseId()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ protected override CarouselViewController2 CreateController(CarouselView newElem

protected override UICollectionViewLayout SelectLayout()
{
bool IsHorizontal = VirtualView.ItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal;
UICollectionViewScrollDirection scrollDirection = IsHorizontal ? UICollectionViewScrollDirection.Horizontal : UICollectionViewScrollDirection.Vertical;
bool isHorizontal = VirtualView.ItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal;

NSCollectionLayoutDimension itemWidth = NSCollectionLayoutDimension.CreateFractionalWidth(1);
NSCollectionLayoutDimension itemHeight = NSCollectionLayoutDimension.CreateFractionalHeight(1);
Expand All @@ -55,7 +54,7 @@ protected override UICollectionViewLayout SelectLayout()
return null;
}
double sectionMargin = 0.0;
if (!IsHorizontal)
if (!isHorizontal)
{
sectionMargin = VirtualView.PeekAreaInsets.VerticalThickness / 2;
var newGroupHeight = environment.Container.ContentSize.Height - VirtualView.PeekAreaInsets.VerticalThickness;
Expand All @@ -81,19 +80,19 @@ protected override UICollectionViewLayout SelectLayout()

if (OperatingSystem.IsIOSVersionAtLeast(16))
{
group = IsHorizontal ? NSCollectionLayoutGroup.GetHorizontalGroup(groupSize, item, 1) :
group = isHorizontal ? NSCollectionLayoutGroup.GetHorizontalGroup(groupSize, item, 1) :
NSCollectionLayoutGroup.GetVerticalGroup(groupSize, item, 1);
}
else
{
group = IsHorizontal ? NSCollectionLayoutGroup.CreateHorizontal(groupSize, item, 1) :
group = isHorizontal ? NSCollectionLayoutGroup.CreateHorizontal(groupSize, item, 1) :
NSCollectionLayoutGroup.CreateVertical(groupSize, item, 1);
}

// Create our section layout
var section = NSCollectionLayoutSection.Create(group: group);
section.InterGroupSpacing = itemSpacing;
section.OrthogonalScrollingBehavior = IsHorizontal ? UICollectionLayoutSectionOrthogonalScrollingBehavior.GroupPagingCentered : UICollectionLayoutSectionOrthogonalScrollingBehavior.None;
section.OrthogonalScrollingBehavior = isHorizontal ? UICollectionLayoutSectionOrthogonalScrollingBehavior.GroupPagingCentered : UICollectionLayoutSectionOrthogonalScrollingBehavior.None;
section.VisibleItemsInvalidationHandler = (items, offset, env) =>
{
//This will allow us to SetPosition when we are scrolling the items
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#nullable disable
using CoreGraphics;
using Foundation;
using Microsoft.Maui.Graphics;
using UIKit;

namespace Microsoft.Maui.Controls.Handlers.Items2
{
internal sealed class CarouselTemplatedCell2 : TemplatedCell2
{
internal new const string ReuseId = "Microsoft.Maui.Controls.CarouselTemplatedCell2";

[Export("initWithFrame:")]
[Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)]
public CarouselTemplatedCell2(CGRect frame) : base(frame)
{
}

private protected override Size GetMeasureConstraints(UICollectionViewLayoutAttributes preferredAttributes)
=> preferredAttributes.Size.ToSize();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ protected override string DetermineCellReuseId(NSIndexPath indexPath)
return base.DetermineCellReuseId(itemIndex);
}

private protected override (Type CellType, string CellTypeReuseId) DetermineTemplatedCellType()
=> (typeof(CarouselTemplatedCell2), CarouselTemplatedCell2.ReuseId);

protected override Items.IItemsViewSource CreateItemsViewSource()
{
var itemsSource = ItemsSourceFactory2.CreateForCarouselView(ItemsView.ItemsSource, this, ItemsView.Loop);
Expand Down Expand Up @@ -506,54 +509,49 @@ async Task UpdateInitialPosition()
return;
}

int position = carousel.Position;
var currentItem = carousel.CurrentItem;

if (currentItem != null)
{
// Sometimes the item could be just being removed while we navigate back to the CarouselView
var positionCurrentItem = ItemsSource.GetIndexForItem(currentItem).Row;
if (positionCurrentItem != -1)
{
position = positionCurrentItem;
}
}

var projectedPosition = NSIndexPath.FromItemSection(position, _section);

if (LoopItemsSource.Loop)
{
//We need to set the position to the correct position since we added 1 item at the beginning
projectedPosition = GetScrollToIndexPath(position);
}

var uICollectionViewScrollPosition = IsHorizontal ? UICollectionViewScrollPosition.CenteredHorizontally : UICollectionViewScrollPosition.CenteredVertically;

await Task.Delay(100).ContinueWith((t) =>
await Task.Delay(100).ContinueWith(_ =>
{
MainThread.BeginInvokeOnMainThread(() =>
{
if (!IsViewLoaded)
{
return;
}

InitialPositionSet = true;

if (ItemsSource is null || ItemsSource.ItemCount == 0)
{
return;
}

int position = carousel.Position;
var currentItem = carousel.CurrentItem;

if (currentItem != null)
{
// Sometimes the item could be just being removed while we navigate back to the CarouselView
var positionCurrentItem = ItemsSource.GetIndexForItem(currentItem).Row;
if (positionCurrentItem != -1)
{
position = positionCurrentItem;
}
}

var projectedPosition = LoopItemsSource.Loop
? GetScrollToIndexPath(position) // We need to set the position to the correct position since we added 1 item at the beginning
: NSIndexPath.FromItemSection(position, _section);

var uICollectionViewScrollPosition = IsHorizontal ? UICollectionViewScrollPosition.CenteredHorizontally : UICollectionViewScrollPosition.CenteredVertically;

CollectionView.ScrollToItem(projectedPosition, uICollectionViewScrollPosition, false);

//Set the position on VirtualView to update the CurrentItem also
SetPosition(position);

UpdateVisualStates();
});

});

}

void UpdateVisualStates()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public void UpdateLayout(UICollectionViewLayout newLayout)

if (newLayout is UICollectionViewCompositionalLayout compositionalLayout)
{
// Note: on carousel layout, the scroll direction is always vertical to achieve horizontal paging with snapping.
// Thanks to it, we can use OrthogonalScrollingBehavior.GroupPagingCentered to scroll the section horizontally.
// And even if CarouselView is vertically oriented, each section scrolls horizontally — which results in the carousel-style behavior.
ScrollDirection = compositionalLayout.Configuration.ScrollDirection;
}

Expand Down Expand Up @@ -330,10 +333,9 @@ protected virtual string DetermineCellReuseId(NSIndexPath indexPath)

var dataTemplate = ItemsView.ItemTemplate.SelectDataTemplate(item, ItemsView);

var cellType = typeof(TemplatedCell2);

var orientation = ScrollDirection == UICollectionViewScrollDirection.Horizontal ? "Horizontal" : "Vertical";
var reuseId = $"{TemplatedCell2.ReuseId}.{orientation}.{dataTemplate.Id}";
(Type cellType, var cellTypeReuseId) = DetermineTemplatedCellType();
var reuseId = $"{cellTypeReuseId}.{orientation}.{dataTemplate.Id}";

if (!_cellReuseIds.Contains(reuseId))
{
Expand All @@ -347,6 +349,9 @@ protected virtual string DetermineCellReuseId(NSIndexPath indexPath)
return ScrollDirection == UICollectionViewScrollDirection.Horizontal ? HorizontalDefaultCell2.ReuseId : VerticalDefaultCell2.ReuseId;
}

private protected virtual (Type CellType, string CellTypeReuseId) DetermineTemplatedCellType()
=> (typeof(TemplatedCell2), TemplatedCell2.ReuseId);

protected virtual void RegisterViewTypes()
{
CollectionView.RegisterClassForCell(typeof(HorizontalDefaultCell2), HorizontalDefaultCell2.ReuseId);
Expand Down
21 changes: 15 additions & 6 deletions src/Controls/src/Core/Handlers/Items2/iOS/TemplatedCell2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ public override UICollectionViewLayoutAttributes PreferredLayoutAttributesFittin

if (PlatformHandler?.VirtualView is { } virtualView)
{
var constraints = ScrollDirection == UICollectionViewScrollDirection.Vertical
? new Size(preferredAttributes.Size.Width, double.PositiveInfinity)
: new Size(double.PositiveInfinity, preferredAttributes.Size.Height);
var constraints = GetMeasureConstraints(preferredAttributes);

if (_measureInvalidated || _cachedConstraints != constraints)
{
Expand All @@ -98,9 +96,12 @@ public override UICollectionViewLayoutAttributes PreferredLayoutAttributesFittin
_needsArrange = true;
}

var size = ScrollDirection == UICollectionViewScrollDirection.Vertical
? new Size(preferredAttributes.Size.Width, _measuredSize.Height)
: new Size(_measuredSize.Width, preferredAttributes.Size.Height);
var preferredSize = preferredAttributes.Size;
// Use measured size only when unconstrained
var size = new Size(
double.IsPositiveInfinity(constraints.Width) ? _measuredSize.Width : preferredSize.Width,
double.IsPositiveInfinity(constraints.Height) ? _measuredSize.Height : preferredSize.Height
);

preferredAttributes.Frame = new CGRect(preferredAttributes.Frame.Location, size);
preferredAttributes.ZIndex = 2;
Expand All @@ -111,6 +112,14 @@ public override UICollectionViewLayoutAttributes PreferredLayoutAttributesFittin
return preferredAttributes;
}

private protected virtual Size GetMeasureConstraints(UICollectionViewLayoutAttributes preferredAttributes)
{
var constraints = ScrollDirection == UICollectionViewScrollDirection.Vertical
? new Size(preferredAttributes.Size.Width, double.PositiveInfinity)
: new Size(double.PositiveInfinity, preferredAttributes.Size.Height);
return constraints;
}

public override void LayoutSubviews()
{
base.LayoutSubviews();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ void ExecuteRemoveItemsCommand()
while (Items.Count > 0)
{
Items.Remove(Items.Last());
Items.Remove(Items.Last());
Items.Remove(Items.Last());
}
RemoveAllItemsCommand.ChangeCanExecute();
RemoveLastItemCommand.ChangeCanExecute();
Expand Down
Loading
Loading