Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can I use one storyboard for 4" and 3.5" iphone screens with autolayout (ios6 + ios7)?

While there are many questions and answers about building a storyboard layout that would work both on 4" and 3.5" screen sizes, I couldn't find a suitable solution for the following scenario.

I use autolayout with ios6 (and ios7), and I don't have to support landscpae or ipad. I have a UIView with several subviews, which have to look as the mockup below. It is easy to set up autolayout constraints in the storyboard to fit either of the screen sizes. My question is - how do I make autolayout choose the correct constraints depending on the screen size at runtime?

SCREEN MOCKUPS

Note, that I DONT want to use 2 different storyboards. Doing so across my whole application would be a lot of work, and I would have to hook up all the delegates, outlets and actions on each storyboard. A change in a screen would require me to do double the work.

I have tried 2 methods to make this work on one storyboard, but I'm not satisfied with either of them.

  • Double the constraints. The larger constraint (50) has a higher priority than the lower constraint (30). The problem with this approach is that on the 3.5" screen size, autolayout may pick a just few lower priority constraints - enough to satisfy the layout - but leave some high priority constraints.

double constraints

  • Subclass NSLayoutConstraint. In this method, all the constraints in the storyboard are set to be NSDualLayoutConstraint. In in initialization code of NSDualLayoutConstraint, the constant of the constraint is changed to the value of 3_5_constant in case the runtime screen size is 3.5". this method is more deterministic, but you can't see the 3.5" layout in the interface builder preview.

enter image description here


If only interface builder constraints had a secondary constant value that would be applied when the screen size is 3.5", it would solve my problem.. So I remain with my question - how can I properly use a single storyboard to layout its subviews correctly for 4" AND 3.5" screen sizes?

like image 395
gardenofwine Avatar asked Oct 29 '13 12:10

gardenofwine


4 Answers

If you want to use only one storyboard and you do not want to utilize auto layout, which would make your life a lot easier for what you've shown in your diagram, you will have to layout your views in code.

You will just need to detect if the user is running on a 4" device and layout your views accordingly.

#define IS_568_SCREEN (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)

if (IS_568_SCREEN) {
    // Lots of code to layout for 4" devices
} else {
    // Lots of code to layout for 3.5" devices
}

However, if you were to use autolayout for this, you'd find it's going to save you a ton of time and code. Instead of having to manually layout every view in code using the solution I mentioned above, you'd simply need to update the y and height constraints depending on the device.

Considering this diagram showing what autolayout would handle for you and what you'd need to update manually, this should help paint a better picture of just how much you'll save with utilizing autolayout.

enter image description here

#define IS_568_SCREEN (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)

if (IS_568_SCREEN) {
    self.layoutConstraintY.constant = 50.0f;
    self.layoutConstraintHeight.constant = 248.0f;
} else {
    self.layoutConstraintY.constant = 30.0f;
    self.layoutConstraintHeight.constant = 220.0f;
}
[self layoutIfNeeded];
like image 83
Jeremy Fox Avatar answered Nov 18 '22 17:11

Jeremy Fox


This stackoverflow answer has solved the same problem for me.

Key is make an IBOutlet to the constraint (e.g height). Then do something like this

- (void)updateViewConstraints {
    [super updateViewConstraints];

    self.myConstraintFromIB.constant =
        [UIScreen mainScreen].bounds.size.height > 480.0f ? 200 : 100;
}
like image 26
carbonr Avatar answered Nov 18 '22 19:11

carbonr


You will need to edit your constraints programatically. You may find this question helpful for that.

You could also have two separate Storyboard files, or two viewController scenes in one storyboard file.

like image 1
WolfLink Avatar answered Nov 18 '22 18:11

WolfLink


How about adding an extra view and including the square view inside it? The extra view should be transparent so no-one sees it. Set the constraints of the extra view to expand with the screen size and set the constraints of the square view to be centred in the extra box. Select a multiplier for the square view size relative to the extra box

like image 1
Martin Lockett Avatar answered Nov 18 '22 17:11

Martin Lockett