public override void PrepareLayout() { base.PrepareLayout(); var sectionCount = CollectionView.NumberOfSections(); if (sectionCount == 0) { return; } // Reset Cache _cachedAttributes.Clear(); _contentBounds = new CGRect(CGPoint.Empty, CollectionView.Bounds.Size); var itemCount = CollectionView.NumberOfItemsInSection(0); var currentIndex = 0; var itemStyle = DetermineItemStyle(itemCount); var lastFrame = CGRect.Empty; var cvWidth = CollectionView.Bounds.Width; var cvHeight = CollectionView.Bounds.Height; while (currentIndex < itemCount) { CGRect segmentFrame; var segmentRects = new List <CGRect>(); switch (itemStyle) { case MosaicStyle.FullWidth: segmentFrame = new CGRect(0, lastFrame.GetMaxY() + 1, cvWidth, cvHeight); segmentRects.Add(segmentFrame); break; case MosaicStyle.HalfWidth: segmentFrame = new CGRect(0, lastFrame.GetMaxY() + 1, cvWidth, cvHeight / 2); var slices = segmentFrame.DividedIntegral((nfloat)0.5, CGRectEdge.MinXEdge); segmentRects.Add(slices["First"]); segmentRects.Add(slices["Second"]); break; case MosaicStyle.TwoThirdsByOneThird: segmentFrame = new CGRect(0, lastFrame.GetMaxY() + 1, cvWidth, cvHeight / 3); var twoThirdsHorizontalSlices = segmentFrame.DividedIntegral((nfloat)(2.0 / 3.0), CGRectEdge.MinXEdge); var twoThirdsVerticalSlices = segmentFrame.DividedIntegral((nfloat)0.5, CGRectEdge.MinYEdge); segmentRects.Add(twoThirdsHorizontalSlices["First"]); segmentRects.Add(twoThirdsVerticalSlices["First"]); segmentRects.Add(twoThirdsVerticalSlices["Second"]); break; case MosaicStyle.OneThirdByTwoThirds: segmentFrame = new CGRect(0, lastFrame.GetMaxY() + 1, cvWidth, cvHeight / 3); var oneThirdHorizontalSlices = segmentFrame.DividedIntegral((nfloat)(1.0 / 3.0), CGRectEdge.MinXEdge); var oneThirdVerticalSlices = segmentFrame.DividedIntegral((nfloat)0.5, CGRectEdge.MinYEdge); segmentRects.Add(oneThirdVerticalSlices["First"]); segmentRects.Add(oneThirdVerticalSlices["Second"]); segmentRects.Add(oneThirdHorizontalSlices["Second"]); break; } // cache attributes. foreach (var rect in segmentRects) { var indexPath = NSIndexPath.FromRowSection(currentIndex, 0); var attributes = UICollectionViewLayoutAttributes.CreateForCell(indexPath); attributes.Frame = rect; _cachedAttributes.Add(attributes); _contentBounds = _contentBounds.UnionWith(lastFrame); currentIndex++; lastFrame = rect; } // determine style for next segment switch (itemCount - currentIndex) { case 1: itemStyle = MosaicStyle.FullWidth; break; case 2: itemStyle = MosaicStyle.HalfWidth; break; default: switch (itemStyle) { case MosaicStyle.FullWidth: itemStyle = MosaicStyle.HalfWidth; break; case MosaicStyle.HalfWidth: itemStyle = MosaicStyle.TwoThirdsByOneThird; break; case MosaicStyle.TwoThirdsByOneThird: itemStyle = MosaicStyle.OneThirdByTwoThirds; break; case MosaicStyle.OneThirdByTwoThirds: itemStyle = MosaicStyle.HalfWidth; break; } break; } } }