Why viewWillTransitionToSize pass wrong size in? - ios

I adjust a constraint in a iOS8 rotation delegate method, but size is not the same what I can see on device, why?
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
println("size: \(size)")
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
widthConstraint.constant = (size.width / 8.0) - 4.0
}
size: (1024.0,768.0)
But real size is smaller then full iPad size.
Testing on real device, and viewController is an embedded container view controller.
It seems in somehow I get the parentViewController's view size.

Related

iOS - Wrong UIScreen bounds in viewWillTransition for iPad

I have to check if my device has changed orientation in iOS 8+.
My approach is:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
let isLand = UIScreen.main.bounds.width > UIScreen.main.bounds.height
coordinator.animate(alongsideTransition: nil) { _ in
let isLand2 = UIScreen.main.bounds.width > UIScreen.main.bounds.height
print("\(isLand) -> \(isLand2)")
}
}
it works fine in iPhone but in iPad isLand has already the new value which should be after the orientation completion, so:
Portrait > Landscape: true -> true
Landscape > Portrait: false -> false
According to the documentation the bounds should change with the orientation so it should have a before/after bounds, shouldn't it?
UIScreen main bounds:
This rectangle is specified in the current coordinate space, which
takes into account any interface rotations in effect for the device.
Therefore, the value of this property may change when the device
rotates between portrait and landscape orientations.
Whereas it works fine both iPhone and iPad if I use the bounds of the current root view controller like this:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
let isLand = UIApplication.shared.keyWindow!.rootViewController!.view.bounds.width > UIApplication.shared.keyWindow!.rootViewController!.view.bounds.height
coordinator.animate(alongsideTransition: nil) { _ in
let isLand2 = UIApplication.shared.keyWindow!.rootViewController!.view.bounds.width > UIApplication.shared.keyWindow!.rootViewController!.view.bounds.height
print("\(isLand) -> \(isLand2)")
}
}
Portrait > Landscape: false -> true
Landscape > Portrait: true -> false
You should try using the containerView of the coordinator context instead.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
let isLand = coordinator.containerView.bounds.width > coordinator.containerView.bounds.height
coordinator.animate(alongsideTransition: nil) { _ in
let isLand2 = coordinator.containerView.bounds.width > coordinator.containerView.bounds.height
print("\(isLand) -> \(isLand2)")
}
}
If you want to get further information regarding the transition you can use the func view(forKey: UITransitionContextViewKey) and func viewController(forKey: UITransitionContextViewControllerKey) using the .from key.

How to use new method in IOS 8 to find screenwidth when view size changes

There is the following method in IOS 8 that is supposed to be used when a view's orientation changes:
override func viewWillTransitionToSize(size: CGSize,
withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
}
How can I use this to find the new width of the screen (I am making a keyboard app) when the screen rotates?
you get the size passed as a parameter...

How to get the size of a UICollectionView cell before rotation

I have a UICollectionView that has a width that is a percentage of it's parent. When it rotates I need to know what the size it is going to be, so I can invalidate the layout and redraw the collection view cells to be the new full width. I was using viewWillTransitionToSize:withTransitionCoordinator: method, but the size it returns is of the entire screen. Is there any easy way to get the new frame of a UICollectionView before the orientation change takes effect?
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
print(self.collectionView.frame) // old frame
coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in
}) { (UIViewControllerTransitionCoordinatorContext) -> Void in
print(self.collectionView.frame) // new frame
}
}

Resize UICollectionView after view transition

I've built detail view in Interface Builder showing informations and photos about some object. Because lenght of informations and number of photos will vary, all is nested in UIScrollView.
Photos are shown in UICollectionView, but I need to always show all contained photos, so I disabled scrolling and dynamically changing Height constraint of UICollectionView by this function (called when finishing rendering cells):
func resizePhotosCollectionView() {
photosCollectionViewHeightConstraint.constant = photosCollectionView.collectionViewLayout.collectionViewContentSize()
}
It works great until this UICollectionView needs resize (typically by device orientation change). I am trying to use UIViewControllerTransitionCoordinator in function:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition(nil) { context in
self.resizePhotosCollectionView()
}
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
but result is jerky because Height constraint changed after transition is complete.
Is there any way how to automatically resize UICollectionView after view transition? If not, how to animate Height constraint change during transition?
Using Xcode 6.1 for target IOS 8.
If I recall correctly, you need to layout the view immediately.
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition(nil) { context in
self.resizePhotosCollectionView()
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
Have you tried wrapping your constraint update into a view animation?
photosCollectionViewHeightConstraint.constant =
photosCollectionView.collectionViewLayout.collectionViewContentSize()
photosCollectionView.setNeedsUpdateConstraints()
UIView.animateWithDuration(0.3, animations: { () -> Void in
photosCollectionView.layoutIfNeeded()
})

Automatically update preferredContentSize upon rotation

I am looking for a way to enforce a UIPopoverPresentationController automatically resize to fill most of the screen, minus say 50 units of padding.
I first tried settings the preferredContentSize in viewDidLoad, and then detect when rotation occurs and update that CGSize to the new size I could calculate. But for some reason, this isn't working in my context. I was using UIDeviceOrientationDidChangeNotification which normally calls the method, but it's not called when the popover exists within a photo editing extension.
I am wondering if there's any other way to change the popover size besides manually updating the preferredContentSize after detecting a size change? If not, is there a way to detect rotation from within this popover in this context?
Try this:
func isLandscape() -> Bool {
// your logical here
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let myNewSize = isLandscape() ? mySizeLandscape : mySizePortrait
self.preferredContentSize = myNewSize
super.viewWillTransition(to: myNewSize, with: coordinator)
}

Resources