2


I have a CollectionView with 3 Cells which extend across the whole device's screen and basically represent my 3 main views.
I have paging enabled, so it basically works exactly like the iOS home screen right now.
My problem is that I want the "default" position of this CollectionView to be equal to view.frame.width so that the second Cell is the "default" view and I can swipe left and right to get to my secondary views.
I have already tried via

collectionView.scrollToItem()

and

collectionView.scrollRectToVisible()

as well as

collectionView.setContentOffset()

but they all seem to work only after the view has loaded (I tried them via a button in my navigation bar). Thank you in advance!


EDIT:
Now this works, but I also have another collection view in that one middle cell which holds a list of little 2-paged UICollectionViews which are actually objects from a subclass of UICollectionViewCell called PersonCell each holding a UICollectionView. I want these UICollectionViews to be scrolled to index 1 as well, this is my code:

for tabcell in (collectionView?.visibleCells)! {
    if let maincell: MainCell = tabcell as? MainCell {
        for cell in maincell.collectionView.visibleCells {
            if let c = cell as? PersonCell {
                c.collectionView.scrollToItem(at: (NSIndexPath(item: 1, section: 0) as IndexPath), at: [], animated: false)
            }
        }
    }
}

This is executed in the viewDidLayoutSubviews of my 'root' CollectionViewController.



EDIT 2: Now I tried using following code in the MainCell class (it's a UICollectionViewCell subclass):

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    let personCell = cell as! PersonCell
    personCell.collectionView.scrollToItem(at: (NSIndexPath(item: 1, section: 0) as IndexPath), at: [], animated: false)
}



EDIT 3:
Long story short, I basically need a delegate method that is called after a cell has been added to the UICollectionView.

unixb0y
  • 979
  • 1
  • 10
  • 39

2 Answers2

2

Did you try [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];

Try calling the code in viewDidLayoutSubviews

Alejandro Vargas
  • 1,327
  • 12
  • 26
0

Okay, I got it!
This SO answer gave me the final hint:
https://stackoverflow.com/a/16071589/3338129
Basically, now I just do this after initialization of the Cell:

self.collectionView.alpha = 1
self.data = data // array is filled with data
self.collectionView.reloadData()
DispatchQueue.main.async {
    for cell in self.collectionView.visibleCells {
        (cell as! PersonCell).collectionView.scrollToItem(at: (NSIndexPath(item: 1, section: 0) as IndexPath), at: [], animated: false)
    }
    self.collectionView.alpha = 1
}

Basically, the code in the DispatchQueue.main.async{...} is called on the next UI refresh cycle which means at a point where the cells are already there. To prevent the user from seeing the wrong page for a fraction of a second, I set the whole collectionView's alpha to 0 and toggle it on as soon as the data is there, the cell is there and the page has scrolled.

unixb0y
  • 979
  • 1
  • 10
  • 39
  • In my case, I push the view controller in a navBarVC, the page will blink when the collectionView alpha changed from 0 to 1. – Jakehao Aug 26 '19 at 12:37