14

I calculate itemSize dependent on safe area for UICollectionView with horizontal scroll and custom layout.

image

But for iPhone X safe area has different size for different orientation. My question is how should I calculate safe area size for landscape orientation in viewWillTransition function? Or how is it possible to do without this calculation?

Abdul Waheed
  • 4,540
  • 6
  • 35
  • 58
bogmila
  • 143
  • 1
  • 6

2 Answers2

11

EDIT

To get safe area size without creating any additional views, use this:

view.safeAreaLayoutGuide.layoutFrame.size

If you want to use viewWillTransition method you can use this:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    // Before rotation
    print(view.safeAreaLayoutGuide.layoutFrame.size)

    coordinator.animate(alongsideTransition: { (context) in
        // During rotation
    }) { (context) in
        // After rotation
        print(self.view.safeAreaLayoutGuide.layoutFrame.size)
    }
}

In the completion block you will get your desired size, note however, that this code will be called after the rotation.

Original answer

Solution using additional UIView:

What I did was to create a UIView and pin it with constant 0 to Safe Area Guides, so that it always matches size of Safe Area:

enter image description here

I created an @IBOutlet of that UIView and in viewDidLayoutSubviews() check the size:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    print(containerView.frame.size)
}

After rotation I also get the updated size of that UIView.

jonaszmclaren
  • 2,459
  • 20
  • 30
  • It is actually good size in viewDidLayoutSubviews method but I need know this size earlier (before rotation will end). Getting size may be done without additional UIView - self.view.safeAreaLayoutGuide.layoutFrame.size gives good results. Your answer unfortunately not fix my problem. – bogmila Sep 19 '17 at 14:43
  • In this case I don't know if it's possible to obtain a size, that isn't laid out yet. Why cannot you calculate that after rotation? Also, here's nice tutorial on custom layout for UICollectionView: https://www.raywenderlich.com/164608/uicollectionview-custom-layout-tutorial-pinterest-2 – jonaszmclaren Sep 19 '17 at 15:29
  • I have updated my answer so it uses `viewWillTransition` method, however the completion block is called after the rotation. It's the closest solution to your problem I have found. – jonaszmclaren Sep 20 '17 at 06:01
  • Thanks. Yes, it is close, but after rotation for a moment appears old view. And it doesn't look good. Finally I used viewDidLayoutSubviews function. But this function is called many times, so in viewWillTransition i set orientationChanged variable to true and in viewDidLayoutSubviews i checked this variable and recalculated sizes. It is satisfying solution for me. Thanks for your help. – bogmila Sep 20 '17 at 09:12
  • Glad to help @bogmila – jonaszmclaren Sep 20 '17 at 09:22
0

Use UICollectionViewDelegateFlowLayout's collectionView(_:layout:sizeForItemAt:). Works like a charm. Setting the size in the completion block of coordinator.animate(alongsideTransition:completion:) in viewWillTransition(to:with:) didn't work for me because the size animation occurs after the orientation animation ends, which looks weird.

GK100
  • 3,664
  • 1
  • 26
  • 19