Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with pagination in UICollectionView when orientation changes

enter image description hereenter image description here
I'm preparing a GridView with all orientation support (height & width resizing) and paging enabled.

In my sample in have taken a 3*3 Grid and to show it like that I have added some dummy transparent cell at the last page.

The issue is when I'm at last page and there I'm changing my orientation from landscape to portrait the pagination doesn't work.

I have used this code in willRotateToInterfaceOrientation:

CGPoint scrollTo = CGPointMake(self.frame.size.width * mPageControl.currentPage, 0);
[self setContentOffset:scrollTo animated:YES];

But still page moves to a page before the last page when going from landscape to portrait and while changing portrait to landscape it works fine.

like image 530
Arun_ Avatar asked Sep 06 '13 08:09

Arun_


2 Answers

Had the same problem, my UICollectionView was paginated, when I scrolled to page 2 in portrait mode and then switched to landscape, the content offset would be set to (72, 0), and this would persist.

The controller was registered for orientation changes where it invalidated the layout, but setting the offset in there didn't help.

What did help was setting the offset inside the layout class' prepareForLayout method. I used

self.collectionView.contentOffset = CGPointMake(ceil(self.collectionView.contentOffset.x/self.collectionView.frame.size.width)*self.collectionView.frame.size.width, self.collectionView.contentOffset.y);

Ceiling is used because floor would always go back to the previous page (and page 0 always paginates fine).

If you're not using a custom layout, you can still subclass flow layout and override that one function.

like image 74
meelawsh Avatar answered Sep 22 '22 21:09

meelawsh


I manage to solve this by setting notification when screen orientation changes and reloading cell which set itemsize according to screen orientation and setting indexpath to previous cell. This does work with flowlayout too. Here is the code i wrote:

var cellWidthInLandscape: CGFloat = 0 {
    didSet {
        self.collectionView.reloadData()
    }
}

var lastIndex: Int = 0

override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.dataSource = self
    collectionView.delegate = self
    NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
    cellWidthInLandscape = UIScreen.main.bounds.size.width

}
deinit {
    NotificationCenter.default.removeObserver(self)
}
@objc func rotated() {

        // Setting new width on screen orientation change
        cellWidthInLandscape = UIScreen.main.bounds.size.width

       // Setting collectionView to previous indexpath
        collectionView.scrollToItem(at: IndexPath(item: lastIndex, section: 0), at: .right, animated: false)
}
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

   // Getting last contentOffset to calculate last index of collectionViewCell
    lastIndex = Int(scrollView.contentOffset.x / collectionView.bounds.width)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        // Setting new width of collectionView Cell
        return CGSize(width: cellWidthInLandscape, height: collectionView.bounds.size.height)

}
like image 22
Yuvraj Bashyal Avatar answered Sep 22 '22 21:09

Yuvraj Bashyal