1

I am trying to use auto layout to to position two views like below picture. I know that with iOS 8 and size classes I can create layout for different layouts and it would work. However I am targeting iOS 7 and according to several posts such as https://stackoverflow.com/a/26841899/4170419, iPhone landscape mode of size classes will not work for earlier version. So, how can I position those two views on different orientation according to my picture? Thanks.enter image description here

Community
  • 1
  • 1
Meanteacher
  • 2,031
  • 3
  • 17
  • 48

2 Answers2

0

Compact width compact height size class will not work on iOS7. It will clash with compact width any height sadly.

Very good summary here: How can Xcode 6 adaptive UIs be backwards-compatible with iOS 7 and iOS 6?

For you particular case, I think you might have to resort to some manual work for iOS7. A possible approach would be:

1) Add a UIView between the label area and the right hand side pinned to the top, bottom, label area leading and trailing to superview with size 0. With no content this should end up 0 width.

2) Add a UIView between the label area and the bottom, pinned top to the label area, leading and trailing to the superview and to bottom with size 0. With no content this should end up 0 height.

3) Add IBOutlets for both views into your controller .h file.

4) In viewDidLoad, create and place the MKMapView into the appropriate view for the current orientation.

This gives you on startup the map view in the location you want.

5) Add orientation change detection to your controller. When the orientation changes, remove the MKMapView from its current view and add it to the view for the new orientation.

Not sure this will work, but it might give you what you want on iOS8 and iOS7 with one piece of code.

You may need to add constraints to the views for width/height or set the MKMapView frame to get the dimensions right for each orientation when layout occurs.

Hopefully somebody may come up with an easier solution, but seems size classes are unlikely to help in this case.

Community
  • 1
  • 1
Rory McKinnel
  • 7,936
  • 2
  • 17
  • 28
  • Could you check my answer and comment if you have any suggestions? Thanks. – Meanteacher May 07 '15 at 21:54
  • Looks like a workable solution. I had not realized that the `active` property worked in iOS7? The documentation says available from iOS8. Does it work as you expect on iOS7? – Rory McKinnel May 08 '15 at 06:35
  • I just tried using the `active` property on iOS7 and the code raises an exception as the property does not exist. You may have to remove and add the properties for iOS7 instead. Perhaps swift is different. – Rory McKinnel May 08 '15 at 06:43
  • Thanks Rory. I found how naive I was. I was using iOS 8 simulator to test. This time I tested with iOS 7 simulator and it seems working. Could you check it again and comment if you find any issues. I really appreciate you took your time to test my previous code. – Meanteacher May 08 '15 at 13:54
  • Looks good to me and glad you are all sorted. It is very annoying that Apple missed out this particular size class support in iOS7 as it must be a very common one for people to want to code up. – Rory McKinnel May 08 '15 at 14:48
0

Finally I solved it :) First of all, both of my orientation show that mapview must be aligned to bottom and right of main view. These constraints are fixed. Then just to shut Xcode I set the constraints for portrait orientation.

Since iPad has enough screen state, I applied rotation fix to only iPhone. I am sure it can be written better way so if you have any comments please share. Thanks.

lazy var landscapeLeft: NSLayoutConstraint = {
    return NSLayoutConstraint(item: self.myMap, attribute: .Leading, relatedBy: .Equal, toItem: self.idLabel, attribute: .CenterX, multiplier: 1.0, constant: 0)
    }()

lazy var landscapeTop: NSLayoutConstraint = {
    return NSLayoutConstraint(item: self.myMap, attribute: .Top, relatedBy: .Equal, toItem: self.idLabel, attribute: .Bottom, multiplier: 1.0, constant: 8)
    }()

lazy var portraitLeft: NSLayoutConstraint = {
    return NSLayoutConstraint(item: self.myMap, attribute: .Leading, relatedBy: .Equal, toItem: self.view, attribute: .Leading, multiplier: 1.0, constant: 8)
    }()

lazy var portraitBottom: NSLayoutConstraint = {
    return NSLayoutConstraint(item: self.myMap, attribute: .Top, relatedBy: .Equal, toItem: self.expectedDateLabel, attribute: .Bottom, multiplier: 1.0, constant: 8)
    }()


func fixLayout() {

    if (UIDevice.currentDevice().userInterfaceIdiom ==  UIUserInterfaceIdiom.Phone) && (UIDevice.currentDevice().orientation.isLandscape) {
        self.view.removeConstraint(portraitLeft)
        self.view.removeConstraint(portraitBottom)
        self.view.addConstraint(landscapeLeft)
        self.view.addConstraint(landscapeTop)

    } else {
        self.view.removeConstraint(landscapeLeft)
        self.view.removeConstraint(landscapeTop)
        self.view.addConstraint(portraitLeft)
        self.view.addConstraint(portraitBottom)
    }

}

override func updateViewConstraints() {
    super.updateViewConstraints()
    fixLayout()
}

UPDATE: I was so naive to think that the code I wrote before was compatible with iOS 7 just because it compiled to ios 7 target and worked on iOS 8 simulator. Thanks to @Rory McKinnel, I found out that I was using methods which are not available on iOS 7. This time, I tested on both iOS 7 and iOS 8 simulators and they worked. I hope that is the end of this problem.

Meanteacher
  • 2,031
  • 3
  • 17
  • 48