Skip to content

Instantly share code, notes, and snippets.

@jsuarezruiz
Created December 5, 2019 07:20
Show Gist options
  • Save jsuarezruiz/6cbb45d7a85ec6dfc415ef625cfbf2ee to your computer and use it in GitHub Desktop.
Save jsuarezruiz/6cbb45d7a85ec6dfc415ef625cfbf2ee to your computer and use it in GitHub Desktop.
using System;
using CoreGraphics;
using Foundation;
using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class CarouselViewLayout : ItemsViewLayout
{
readonly CarouselView _carouselView;
readonly ItemsLayout _itemsLayout;
public CarouselViewLayout(ItemsLayout itemsLayout, CarouselView carouselView) : base(itemsLayout)
{
_carouselView = carouselView;
_itemsLayout = itemsLayout;
}
public override bool ShouldInvalidateLayoutForBoundsChange(CGRect newBounds)
{
return false;
}
public override void ConstrainTo(CGSize size)
{
//TODO: Should we scale the items
if (ScrollDirection == UICollectionViewScrollDirection.Horizontal)
{
var width = size.Width - _carouselView.PeekAreaInsets.Left - _carouselView.PeekAreaInsets.Right;
ItemSize = new CGSize(width, size.Height);
}
else
{
var height = size.Height - _carouselView.PeekAreaInsets.Top - _carouselView.PeekAreaInsets.Bottom;
ItemSize = new CGSize(size.Width, height);
}
}
public override CGSize CollectionViewContentSize
{
get
{
var collectionViewContentSize = base.CollectionViewContentSize;
if (ScrollDirection == UICollectionViewScrollDirection.Horizontal)
collectionViewContentSize.Width -= (float)(_carouselView.PeekAreaInsets.Left + _carouselView.PeekAreaInsets.Right);
else
collectionViewContentSize.Height -= (float)(_carouselView.PeekAreaInsets.Top + _carouselView.PeekAreaInsets.Bottom);
return collectionViewContentSize;
}
}
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(CGRect rect)
{
var layoutAttributes = base.LayoutAttributesForElementsInRect(rect);
if (layoutAttributes != null)
{
foreach (var layoutAttribute in layoutAttributes)
{
if (layoutAttribute.RepresentedElementKind == null)
{
var index = layoutAttribute.IndexPath;
var attributesForItem = LayoutAttributesForItem(index);
if (attributesForItem != null)
layoutAttribute.Frame = attributesForItem.Frame;
}
}
}
return layoutAttributes;
}
public override UICollectionViewLayoutAttributes LayoutAttributesForItem(NSIndexPath indexPath)
{
var currentItemAttributes = base.LayoutAttributesForItem(indexPath);
var isFirstItemInSection = indexPath.Item == 0;
if (isFirstItemInSection)
{
var firstFrame = currentItemAttributes?.Frame ?? CGRect.Empty;
if (ScrollDirection == UICollectionViewScrollDirection.Horizontal)
{
var firstWidth = firstFrame.Width + _carouselView.PeekAreaInsets.Left - _carouselView.PeekAreaInsets.Right;
currentItemAttributes.Frame = new CGRect(firstFrame.X - _carouselView.PeekAreaInsets.Left, firstFrame.Y, firstWidth, firstFrame.Height);
}
else
{
var firstHeight = firstFrame.Height + _carouselView.PeekAreaInsets.Top - _carouselView.PeekAreaInsets.Bottom;
currentItemAttributes.Frame = new CGRect(firstFrame.X, firstFrame.Y - _carouselView.PeekAreaInsets.Top, firstFrame.Width, firstHeight);
}
return currentItemAttributes;
}
var currentFrame = currentItemAttributes.Frame;
if (ScrollDirection == UICollectionViewScrollDirection.Horizontal)
currentItemAttributes.Frame = new CGRect(currentFrame.X - _carouselView.PeekAreaInsets.Left, currentFrame.Y, currentFrame.Width, currentFrame.Height);
else
currentItemAttributes.Frame = new CGRect(currentFrame.X, currentFrame.Y - _carouselView.PeekAreaInsets.Top, currentFrame.Width, currentFrame.Height);
return currentItemAttributes;
}
public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
if (_itemsLayout is LinearItemsLayout linearItemsLayout)
return (nfloat)linearItemsLayout.ItemSpacing;
return base.GetMinimumInteritemSpacingForSection(collectionView, layout, section);
}
public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
var insets = base.GetInsetForSection(collectionView, layout, section);
var left = insets.Left + (float)_carouselView.PeekAreaInsets.Left;
var right = insets.Right + (float)_carouselView.PeekAreaInsets.Right;
var top = insets.Top + (float)_carouselView.PeekAreaInsets.Top;
var bottom = insets.Bottom + (float)_carouselView.PeekAreaInsets.Bottom;
return new UIEdgeInsets(top, left, bottom, right);
}
internal void UpdateConstraints(CGSize size)
{
ConstrainTo(size);
UpdateCellConstraints();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment