title: How to create auto sized cells using UICollectionViewCompositionalLayout and multiple cell types?
body: <p>I'm trying to use the new <code>UICollectionViewCompositionalLayout</code> on iOS13. I'd like to show two different cell types, but I want the layout system to auto size the cells. I wanted to leverage <code>NSCollectionLayoutDimension.estimated</code> thinking that auto size would be taken care of for me.</p>
  
  <p>I'm trying to do this with Xamarin, but Swift coders should be able to read the below code fine. I'm not very strong with auto layout and dynamic cell sizes, but I was able to get thus far looking at online resources. Pretty much every <code>UICollectionViewCompositionalLayout</code> example out there seems to be using a single cell template.</p>
  
  <pre><code>public class MyViewController : UIViewController
  {
      private UICollectionView _collectionView;
  
      public static List&lt;BaseModel&gt; Models = new List&lt;BaseModel&gt;();
  
      public override void ViewDidLoad()
      {
          base.ViewDidLoad();
  
          PopulateModels();
  
          _collectionView = new UICollectionView(View.Frame, GetUiCollectionViewLayout())
          {
              BackgroundColor = UIColor.Brown,
              DataSource = new MyViewUICollectionViewDataSource(),
              ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never,
              TranslatesAutoresizingMaskIntoConstraints = false,
              ShowsVerticalScrollIndicator = false,
              ShowsHorizontalScrollIndicator = false
          };
  
          _collectionView.RegisterClassForCell(typeof(MyViewUICollectionViewCell), MyViewUICollectionViewCell.ReuseIdentifier);
          _collectionView.RegisterClassForCell(typeof(MyViewUICollectionViewCell2), MyViewUICollectionViewCell2.ReuseIdentifier);
  
          View.AddSubview(_collectionView);
  
          NSLayoutConstraint.ActivateConstraints(new[]
          {
              _collectionView.TopAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.TopAnchor),
              _collectionView.BottomAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.BottomAnchor),
              _collectionView.LeftAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.LeftAnchor),
              _collectionView.RightAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.RightAnchor)
          });
      }
  
      private static void PopulateModels()
      {
          for (var i = 0; i &lt; 100; i++)
          {
              BaseModel baseModel;
  
              if (i % 2 == 0)
              {
                  baseModel = new Model1
                  {
                      UIColor = UIColor.Red
                  };
              }
              else
              {
                  baseModel = new Model2
                  {
                      Text = "Item " + i
                  };
              }
  
              Models.Add(baseModel);
          }
      }
  
      private UICollectionViewLayout GetUiCollectionViewLayout()
      {
          var layoutSize = NSCollectionLayoutSize.Create(NSCollectionLayoutDimension.CreateFractionalWidth(1), NSCollectionLayoutDimension.CreateEstimated(200));
          var item = NSCollectionLayoutItem.Create(layoutSize);
          var group = NSCollectionLayoutGroup.CreateHorizontal(layoutSize: layoutSize, subitem: item, count: 1);
          var section = NSCollectionLayoutSection.Create(group);
  
          // this is what you need for content inset
          section.ContentInsets = new NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5);
  
          // this is spacing between items
          section.InterGroupSpacing = 5;
  
          var layout = new UICollectionViewCompositionalLayout(section);
  
          return layout;
      }
  }
  
  public class BaseModel
  {
  
  }
  
  public class Model1 : BaseModel
  {
      public UIColor UIColor { get; set; }
  }
  
  public class Model2 : BaseModel
  {
      public string Text { get; set; }
  }
  
  public class MyViewUICollectionViewDataSource : UICollectionViewDataSource
  {
      public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
      {
          var model = MyViewController.Models[(int) indexPath.Item];
  
          switch (model)
          {
              case Model1 model1:
              {
                  var cell = collectionView.DequeueReusableCell(MyViewUICollectionViewCell.ReuseIdentifier, indexPath) as MyViewUICollectionViewCell;
                  cell.ColorView.BackgroundColor = model1.UIColor;
                  return cell;
              }
              case Model2 model2:
              {
                  var cell2 = collectionView.DequeueReusableCell(MyViewUICollectionViewCell2.ReuseIdentifier, indexPath) as MyViewUICollectionViewCell2;
                  cell2.Label.Text = model2.Text;
                  return cell2;
              }
              default:
                  throw new Exception();
          }
      }
  
      public override nint GetItemsCount(UICollectionView collectionView, nint section)
      {
          return MyViewController.Models.Count;
      }
  }
  
  public class MyViewUICollectionViewCell : UICollectionViewCell
  {
      public const string ReuseIdentifier = "MyViewUICollectionViewCell";
  
      public UIView ColorView { get; }
  
      [Export("initWithFrame:")]
      public MyViewUICollectionViewCell(CGRect frame) : base(frame)
      {
          var container = new UIView
          {
              BackgroundColor = UIColor.White,
              TranslatesAutoresizingMaskIntoConstraints = false
          };
  
          container.Layer.CornerRadius = 5;
  
          ContentView.AddSubview(container);
  
          container.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor).Active = true;
          container.LeftAnchor.ConstraintEqualTo(ContentView.LeftAnchor).Active = true;
          container.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor).Active = true;
          container.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor).Active = true;
  
          ColorView = new UIView
          {
              TranslatesAutoresizingMaskIntoConstraints = false
          };
  
          ColorView.Layer.CornerRadius = 10;
  
          container.AddSubview(ColorView);
  
          ColorView.CenterXAnchor.ConstraintEqualTo(container.CenterXAnchor).Active = true;
          ColorView.CenterYAnchor.ConstraintEqualTo(container.CenterYAnchor).Active = true;
          ColorView.WidthAnchor.ConstraintEqualTo(20).Active = true;
          ColorView.HeightAnchor.ConstraintEqualTo(50).Active = true;
      }
  }
  
  public class MyViewUICollectionViewCell2 : UICollectionViewCell
  {
      public const string ReuseIdentifier = "MyViewUICollectionViewCell2";
  
      public UILabel Label { get; }
  
      [Export("initWithFrame:")]
      public MyViewUICollectionViewCell2(CGRect frame) : base(frame)
      {
          var container = new UIView
          {
              BackgroundColor = UIColor.White,
              TranslatesAutoresizingMaskIntoConstraints = false
          };
  
          container.Layer.CornerRadius = 5;
  
          ContentView.AddSubview(container);
  
          container.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor).Active = true;
          container.LeftAnchor.ConstraintEqualTo(ContentView.LeftAnchor).Active = true;
          container.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor).Active = true;
          container.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor).Active = true;
  
          Label = new UILabel
          {
              TranslatesAutoresizingMaskIntoConstraints = false
          };
  
          container.AddSubview(Label);
  
          Label.CenterXAnchor.ConstraintEqualTo(container.CenterXAnchor).Active = true;
          Label.CenterYAnchor.ConstraintEqualTo(container.CenterYAnchor).Active = true;
          //Label.WidthAnchor.ConstraintEqualTo(20).Active = true;
          //Label.HeightAnchor.ConstraintEqualTo(20).Active = true;
      }
  }
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/6Xxnz.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6Xxnz.jpg" alt="enter image description here"></a></p>
  
  <p>As you can see, the problem is both cell types use the same estimated height of 200. I'm not sure what I'm doing wrong here. I want both cell types to be resized automatically to fit their content instead of having extra space to hit 200. I tried using a small estimated size like 10, but that didn't change anything. How should the code be changed to have a working auto size feature?</p>