Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView resets content offset after scrolling a nested UITableView

Setup:

I have a single UICollectionView created on a Storyboard and delegates connected to a controller, oriented for horizontal scroll. Each UICollectionViewCell has a UITableView inside, delegated to the same controller. The Collection view is paged. There are about 3.5 cells visible at a time.

Problem:

If I scroll over horizontally on the collection view so that is now "paged" over 1 length, and then attempt to scroll a contained UITableView vertically, the UICollectionView UNINTENTIONALLY content offset resets by animating to content offset of 0,0. The touch event is maintained, and the dequeued cell continues its scrolling action. I do not want the collection view to reset when a user scrolls the tableview

note:

using the iPad simulators

Sample Picture Here is a sample picture. Each column is a UICollectionViewCell containing a UITableView. Each row within the column is a UITableViewCell. If I am not at Content off set of 0,0 for the UICollectionView, and I scroll on any TableView, the collection view animates back to having a content offset of 0,0

like image 769
Michael Lorenzo Avatar asked Sep 08 '26 04:09

Michael Lorenzo


1 Answers

Little bit outdated answer, but might help someone. First set scrollView delegate in collectionView to return to main view controller.

Declare in view controller:

private var scrollViewOffset: CGPoint = CGPointZero

In main view controller add the following code:

func scrollViewDidScroll(scrollView: UIScrollView) {

        if scrollView == self.tableView {
            return
        }

        self.scrollViewOffset = scrollView.contentOffset

        for cell in self.tableView.visibleCells {
            (cell as! MyCell).collectionView.contentOffset = scrollView.contentOffset
        }
    }

After you did this part, next one is what you're missing:

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

        cell.collectionView.reloadData()
        cell.collectionView.layoutIfNeeded() // THIS PART IS NEEDED IN ORDER NOT TO SCROLL TO 0, 0 OFFSET
        return cell
    }

And in:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        let cell: MyCell = cell as! MyCell
        cell.collectionView.contentOffset = self.scrollViewOffset
    }

Content of the MyCell should be something like this:

protocol MyCellDelegate {
        func scrollViewDidScroll(scrollView: UIScrollView)
    }
    class MyCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
    var delegate: MyCellDelegate? = nil

// Do collection view display logic here
// ...
// After that implement scrollview delegate

    func scrollViewDidScroll(scrollView: UIScrollView) {
            if (self.delegate != nil) {
                self.delegate?.scrollViewDidScroll(scrollView)
            } else {
                print("Missing delegate init")
            }
        }
}

This answer is for Xcode 7.3

like image 50
Baki Avatar answered Sep 09 '26 17:09

Baki