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;
                }
            }
        }