I’m currently working on an iOS app which has an UICollectionView with different
cells, and one of those has inside an UIWebView. Such, renders HTML returned
from an API and, by design specs., the container cell must grow to accommodate
the final web page loaded (similar to what Medium's app does when you tap on an
article).
My question was: how can I achieve such dynamic growth? By one side, is how we
gather the final HTML document’s height, where this simple JavaScript snippet
returns exactly that:
var actualHeight = WebView.EvaluateJavascript("document.body.scrollHeight");
(You’ll need to execute it just before the DOM is loaded, where
UIWebView.LoadFinished is pretty handy.)
By the other one, how do I tell back the UICollectionView that specific cells
need more vertical space? Looking through Google I found out a few articles and
StackOverflow questions which touch this and, don’t know where, found what I
finally implemented: the atrezzo cell technique (the “atrezzo” thing is mine).

Títeres
The idea is as follows: why don’t we create an atrezzo cell -one which never
gets actually added to the collection view- just for computing its size
depending on its content? That way, asynchronously we’ll get the final height
(through above JavaScript) and ask the collection view to reload just that item.
Something like this -in your UICollectionViewSource:
[Export("collectionView:layout:sizeForItemAtIndexPath:")]
public virtual CGSize SizeForItemAtIndexPath(UICollectionView collectionView,
UICollectionViewLayout layout,
NSIndexPath indexPath)
{
[...]
if (_webViewHeight == 0)
{
if (_atrezzoCell == null)
{
_atrezzoCell = NSBundle.MainBundle.LoadNib(nameof(WebViewCell),
this, null)
.GetItem(0);
_atrezzoCell.HeightMeasured += (sender, e) =>
{
_webViewHeight = e.Height;
ReloadItemAction(indexPath);
};
}
var item = GetItemAt(indexPath);
_atrezzoCell.Refresh(item);
_atrezzoCell.SetNeedsLayout();
_atrezzoCell.LayoutIfNeeded();
size = _atrezzoCell.ContentView.SystemLayoutSizeFittingSize(
UIView.UILayoutFittingCompressedSize);
_previousItemHeight = size.Height;
size.Width = collectionView.Frame.Width;
}
else
size = new CGSize(collectionView.Frame.Width,
_previousItemHeight + _webViewHeight);
[...]
return size;
}
I implemented this back in December and last week had a similar task but without
involving UIWebView. Our workmate Oriol made a simple yet powerful approach
without needed those atrezzos so, finally, this time I backed on his solution. I
hope this servers as a poke to him to write how he sorted that out which, for
sure, will be useful for others as well.
Source Url: http://marcoscobena.com/#/last-week-dynamic-cells-height