2

I'm creating an EPG (Electronic Program Guide); to retrieve the program info I use JSON. For the design, I have a table view in the left half for the channel logo and name, and in the right half a collection view for all the TV programs for that channel. The thing is that for every show the collection view row must have a different width that depends on the duration of the show.

I'm building it based on this fantastic example called: EPG Grid

But in this example, all the channels are loaded previously in one array. This works fine if the channels list is short, but in my case the list is very large, so I need to load every channel in tableView:cellForRowAtIndexPath:, then create the layout with the specified width.

Any thoughts about this?

jscs
  • 63,694
  • 13
  • 151
  • 195
garanda
  • 1,271
  • 11
  • 16

2 Answers2

0

I figured out by my self, the thing is in my case not to use UICollectionViewLayout (CustomLayout) use layout Flow and add the collectionView inside tableView like this:

enter image description here enter image description here

Then in every row of tableView delegate the collectionView.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
{        
    let cell: CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomTableViewCell

    cell.collectionView.delegate = self
    cell.collectionView.dataSource = self
    cell.collectionView.tag = indexPath.row

    cell.tag = 100 + indexPath.row;

    return cell;
}

After delegate, the method collectionView:sizeForItemAtIndexPath is called, on this method you must to calculate width or height retrieving data using indexPath

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize 
{
    //Calculation of width based on indexPath

    //...
    return CGSizeMake(width, 89)
}

Finally for making the scroll uniform for all the cells at the same time use the method scrollViewDidScroll. Check this post: Horizontally scroll ALL rows of UICollectionView together

func scrollViewDidScroll(scrollView: UIScrollView) {

    var ret: Bool = false;

    if (self.lastContentOffset > scrollView.contentOffset.x)
    {
        ret = true;
    }
    else if (self.lastContentOffset < scrollView.contentOffset.x)
    {
        ret = true;
    }        

    if(scrollView.isKindOfClass(UICollectionView) && ret)
    {
        self.lastContentOffset = scrollView.contentOffset.x;
        for var i = 0; i < data.count; i++
        {
            let cell = self.view.viewWithTag(100 + i) as? ChannelTableViewCell;

            if(cell != nil)
            {
                let collectionCell: UICollectionView? = cell?.collectionView;

                if(collectionCell != nil)
                {
                    collectionCell!.contentOffset = scrollView.contentOffset;
                }
            }
        }
    }
}
Community
  • 1
  • 1
garanda
  • 1,271
  • 11
  • 16
  • Hi can you share your project, I am implementing same thing using swift and kind of stuck passing data, I am using NSFetchedResultsControllerDelegate, and not understanding when and how to send data to flow layout – Iraniya Naynesh May 07 '18 at 05:40
  • 1
    @garanda I am facing same issue. Did you find the solution ? – Raxit Jul 11 '18 at 11:44
0

This is the only thing that worked for me with Swift 5, I hope it helps.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
{
     super.viewWillTransition(to: size, with: coordinator)
            
     collectionView.collectionViewLayout.invalidateLayout()
     collectionView.frame.size = size
}
maremoto007
  • 104
  • 1
  • 5