My experience with autolayout tells me that it's very difficult to make app look good on whole variety of devices (from iPhone 4s to 6s especially). Size classes are useful with device position and distinguishing between iPhone and iPad.
To make my app look right on each iPhone size, I connected contraints to my viewController and introduce certain multipliers for each size
IBOutlets:
class BodyViewController: UIViewController {
@IBOutlet var mainView: UIView!
@IBOutlet weak var boyImageCenterConstraint: NSLayoutConstraint!
@IBOutlet weak var femaleMaleSegmentedControl: UISegmentedControl!
@IBOutlet weak var boyImage: UIImageView!
@IBOutlet weak var nextButton: UIButton!
@IBOutlet weak var buttonHeight: NSLayoutConstraint!
@IBOutlet weak var infoLabel: UILabel!
@IBOutlet weak var organLabel: UILabel!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
@IBOutlet weak var darkBackgroundWithButtons: UIView!
@IBOutlet weak var buttonToBottom: NSLayoutConstraint!
@IBOutlet weak var buttonToTop: NSLayoutConstraint!
...
I have a method to adjust them accordingly:
func adjustViewDesignBasedOnDevice()
{
let baseMultiplier:CGFloat = 160.0
var multiplier:CGFloat = 0.0
let recognizer = DeviceRecognizer()
let device = recognizer.determineHeightOfDarkBackgroundWithButtons(UIScreen.mainScreen().bounds.height)
switch device
{
case .ip4:
multiplier = 120.0
case .ip5:
multiplier = 140.0
case .ip6:
multiplier = 160.0
case .ip6p:
multiplier = 170.0
case .iPad:
multiplier = 220.0
default:
multiplier = 250.0
}
self.infoLabel.font = infoLabel.font.fontWithSize(13.0 * (multiplier / baseMultiplier))
self.organLabel.font = organLabel.font.fontWithSize(19.0 * (multiplier / baseMultiplier))
let indexHeight = self.darkBackgroundWithButtons.constraints.indexOf(heightConstraint)
let indexButtonToBottom = self.darkBackgroundWithButtons.constraints.indexOf(buttonToBottom)
let indexButtonToTop = self.darkBackgroundWithButtons.constraints.indexOf(buttonToTop)
let indexButton = self.nextButton.constraints.indexOf(buttonHeight)
self.darkBackgroundWithButtons.constraints[indexHeight!].constant = multiplier
self.darkBackgroundWithButtons.constraints[indexButtonToTop!].constant = self.darkBackgroundWithButtons.constraints[indexButtonToTop!].constant * (multiplier / baseMultiplier)
self.darkBackgroundWithButtons.constraints[indexButtonToBottom!].constant = self.darkBackgroundWithButtons.constraints[indexButtonToTop!].constant
self.nextButton.constraints[indexButton!].constant = self.nextButton.constraints[indexButton!].constant * (multiplier / baseMultiplier)
}
This way I achieved the right layout on each device. I tried very hard with auto-layout before I came up with this approach, but failed to make things look good mainly because different width/height ratios in each device size.
Is my approach professional? It it common practice to solve layout issues in similar way?
EDIT:
Until now, I used to use auto-layout for whole iPhone family. Since it's relatively easy to make your layout responsive across iP5 to iP6+, it's very difficult to cover iP4 cause it's height/width ratio is completely different.
As I was told in comments below, I'll add screenshot and elaborate on problem:
Segmented control and girl image are done using autolayout entirely. It is perfectly sufficient solution for them.
However, the issues surfaced with this whole stuff below (dark background with two UILabels, UIButton and colorful strip UIImage)
Using mere autolayout haven't allowed me to adjust the font size correctly(Autoshrinking is a bad idea since labels can be longer, it would spoil symmetry)
Next, I need all sizes to be smaller accordingly, including button sizes, button position, labels position and finally entire dark background size and ratio to change.
Which part of my approach is bad? Detecting device, editing NSLayoutConstraints straight from code, or everything?:)
How senior iOS Devs make their app responsive? I can hardly imagine using autolayout with size classes only
Is it common practice to solve layout issues in a similar way?
Speaking professionally... absolutely not. However, it's hard to show you the correct way without a complete description of the layout you expect to see across all devices. Can you update this question with some information describing exactly how the layout should look? Major bonus points for screenshots. \$\endgroup\$infoLabel
,organLabel
,darkBackgroundWithButtons
, andnextButton
. Have I missed any that you're not managing to set up with autolayout? And can you help me understand which property corresponds to each UI element? By my guess, the info label is the one starting with the word "Dotknij" and the organ label is the one with "GŁOWA"? The next button is the button at the bottom with the check mark? What area specifically is thedarkBackgroundWithButtons
? And can you elaborate on the rules? \$\endgroup\$