UITableView + UICollectionView + UITableView sizing issue

Viewed 379

Below attached image is representing my requirement:

UITableView

In this image the yellow color UITableView will have list of different UITableViewCell items. In one of the UITableViewCell it has UICollectionView with its list of UICollectionViewCell items and the scroll direction for the UICollectionView is set to horizontal

Each UICollectionViewCell will have one UITableView (Highlighted in Red Color) and it will have its list of UITableViewCell (Highlited in Rose Color) items. Here, the UITableViewCell (Highlited in Rose Color) item can collapse/expand. Whenever the cell is collapse/expand the red table's content size is handled automatically. But, whenever the red table's content size is increased the collectionview size is not increasing.

I have added all relevant constraints to these UI elements. But, the content size or frame of the collectionview is not expanding when a tableview cell is expanded.

To understand better here i am breaking it down how the views are designed:

  1. Yellow tableview embedded inside a UIViewController and it will have one simple UITableViewCell which has no custom class
  2. To the cell programatically the UICollectionView will be added. This UICollectionView is placed in one xib file and it has embeded inside a UIView
  3. UICollectionViewCell has been created in one xib and it will have UITableView element inside.
  4. Also, UITableViewCell has its own xib to refer and this is the cell which will gets expand/collapse

I have tried modifying the intrinsicContentSize property to modify the UICollectionView property's height where it has embedded inside UIView element whenever the expand is happening. Please, refer the CardView.swift for the reference.

CardView.swift

I know the design is bit complex. But, what am i missing here?

3 Answers

Based on your requirement in the image, I just created a sample project here.

I did not use separate Xibs. However, I was able to achieve what you asked for. You might have to handle the reload of the innermost tableView better based on your apps business logic.

Here's what I have implemented:

  1. The top most view controller has a parent table view.
  2. This table view cell consists of a child collection view.
  3. The child collection view cell consists of a grand child table view.
  4. The grand child table view is the one corresponding to the table view Highlited in Rose Color in the question.
  5. To answer your question about the collection view not expanding: to expand the child collection view when the grandchild table view cell is tapped, I am reloading the parent table view by increasing the row height for the cell containing the collection view. Hence you don't have to worry about adjusting the constraints in auto layout
  6. In case you want to add additional content into the child collection view cell, you can add a height constraint to the grand child table view with a low priority and modify that whenever you need to expand the content in the grand child table view.
  7. if you want to achieve point 6, as suggested by @Ramy Al Zuhouri, you might have to call: collectionView.performBatchUpdates before collectionView.reloadData() to expand the cell size

Refer to the video below for better understanding

enter image description here

This doesn't necessarily solve your problem, but sometimes it's a matter of forcing the collection view to invalidate its layout and recalculating its size. I once received an answer to a TSI from an Apple enginner:

So this is old fashioned way of forcing a re-usable container (Collection || Table) to invalidate its layout. You may even be able to just call invalidate layout. There are oddities in the system with AutoLayout and animations that sometimes throw the system into an odd state. If we do the above the container and can invalidate its layout and make updates without need to re-calculate + incorporate animations. To summarize, calling performBatchUpdates with nil parameters can be useful if you need to force an update based on layout content (not necessarily datasource changes).

It looks like a hack to be used with caution, but it can be worth to give it a try. Whenever you need to recalculate the size of the collection view's cell to expand or shrink, you can do this:

UIView.setAnimationsEnabled(false)
collectionView.performBatchUpdates(nil, completion: nil)
UIView.setAnimationsEnabled(true)
collectionView.reloadData()

This forces a reload, and UIKit is able to recalculate the height of the cell given that you update the height. How? In my case I did by updating a height constraint, but there are multiple ways of doing this. However, it's intended that as the reload happens the collection view should be aware of the new cell height.

the good approach for this, you have to add collectionView in the tableViewHeader then whenever you scroll up your tableView your collectionView section will also scroll up

to load cells on the specific indexes follow bellow steps:

if(indexpath.row == 0){
//load first tableView cell with collection view 
}
else if (indexpath.row == 1){
//load second tableView cell with collection view
}
else{
//load table view cell here
}
Related