Skip to content

Instantly share code, notes, and snippets.

@Mogikan
Last active March 16, 2020 10:34
Show Gist options
  • Save Mogikan/b4bc79f1decf553f4e18c3a6ba387620 to your computer and use it in GitHub Desktop.
Save Mogikan/b4bc79f1decf553f4e18c3a6ba387620 to your computer and use it in GitHub Desktop.
public class VerticalGridLayout : UICollectionViewLayout
{
public VerticalGridLayout(
IGridCellMetricProvider gridMetricProvider,
double cellHeight
)
{
_gridMetricProvider = gridMetricProvider;
_cellHeight = cellHeight;
}
private IGridCellMetricProvider _gridMetricProvider;
private double _cellHeight;
private Dictionary<NSIndexPath, UICollectionViewLayoutAttributes> attributesCache = new Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>();
private nfloat ContentWidth
{
get => CollectionView.Frame.Width - (CollectionView.ContentInset.Left + CollectionView.ContentInset.Right);
}
private nfloat _contentHeigth;
//bounding rect for all items
public override CoreGraphics.CGSize CollectionViewContentSize
{
get
{
var contentHeight = (nfloat)(_gridMetricProvider.GridSize.Height * _cellHeight);
return new CoreGraphics.CGSize(ContentWidth,contentHeight);
//return base.CollectionViewContentSize;
}
}
//which items to show in scrollview
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(CoreGraphics.CGRect rect)
{
return attributesCache.Values.ToArray(); //return base.LayoutAttributesForElementsInRect(rect);
}
//retrieve layout attributes for specific item
public override UICollectionViewLayoutAttributes LayoutAttributesForItem(Foundation.NSIndexPath indexPath)
{
double cellWidth = ContentWidth / _gridMetricProvider.GridSize.Width;
var gridMetrics = _gridMetricProvider.GridCellInfoForIndexPath(indexPath);
var itemAttributes = UICollectionViewLayoutAttributes.CreateForCell(indexPath);
double x = cellWidth * gridMetrics.column;
double w = cellWidth * gridMetrics.colspan;
double y = _cellHeight * gridMetrics.row;
double h = _cellHeight * gridMetrics.rowspan;
itemAttributes.Frame = new CoreGraphics.CGRect(x, y, w, h);
return itemAttributes;
}
//if collection view size changed or device is rotated
public override bool ShouldInvalidateLayoutForBoundsChange(CoreGraphics.CGRect newBounds)
{
if (CollectionView == null)
return false;
return CollectionView.Bounds.Width != newBounds.Width;
}
//for generating cache
public override void PrepareLayout()
{
if (attributesCache.Count != 0) return;
for (int sectionIndex = 0; sectionIndex < CollectionView.NumberOfSections(); sectionIndex++)
{
for (int itemIndex = 0; itemIndex < CollectionView.NumberOfItemsInSection(sectionIndex); itemIndex++)
{
NSIndexPath indexPath = NSIndexPath.FromItemSection(itemIndex, sectionIndex);
attributesCache.Add(indexPath, LayoutAttributesForItem(indexPath));
}
}
}
//}
//clear cache
public override void InvalidateLayout()
{
attributesCache.Clear();
base.InvalidateLayout();
}
}
public interface IGridCellMetricProvider
{
GridCellInfo GridCellInfoForIndexPath(NSIndexPath path);
Size GridSize { get; }
}
public struct GridCellInfo
{
public GridCellInfo(int col,int colspan,int row,int rowspan)
{
this.row = row;
this.rowspan = rowspan;
this.column = col;
this.colspan = colspan;
}
public int column;
public int colspan;
public int row;
public int rowspan;
}
...
CollectionView.SetCollectionViewLayout(new VerticalGridLayout(_dataSource, cellHeight: ApplicationSettings.DefaultCellHeight), false);
...
class which implements IGridCellMetricProvider
...
public GridCellInfo GridCellInfoForIndexPath(NSIndexPath path)
{
var formControl = GetControlAt(path.Row);//row will be index
return new GridCellInfo(formControl.Left, formControl.Width, formControl.Top, formControl.Height);
}
public Size GridSize => new Size(_form.Width,_form.Height);
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment