How to handle Auto Layout with different screen sizes
onmyway133 opened this issue · comments
Auto Layout is awesome. Just declare the constraints and the views are resized accordingly to their parent 's bounds
changes. But sometimes it does not look good, because we have fixed values for padding, width, height, and even fixed font size.
Read more How to make Auto Layout more convenient in iOS
This can be solved by some degree using Size Class
. The idea of size class
is that we have many sets of constraints, and based on the device traits, we enabled some of them. This is more convenient to do in Storyboard (although very hard to reason about), but if we're doing in code (my prefer way), then it is a lot of code. And a lot of code means a lot of bugs.
If you take a look at iOSRes, we see the ratio 16:9
(height:width
)
- iPhone SE (320 x 568): 1.775
- iPhone 6 (375 x 667): 1.778
- iPhone 6+ (414 x 736): 1.778
They mostly have the same ratio. So we can have a simple approach, that scale elements based on ratio. Given the fact that the designer usually designs for iPhone 6 size
, we can make that a base.
In this approach, the content will scale up or down depending on its ratio. You may argue that the idea of bigger phone is to display more, not to show the same content bigger. You may be right, in that case you need to create different constraints and different UIs. But if you want simple solutions that work, this is one of them
This is the technique I used when doing Windows Phone development
, but it applies to many platforms as well
Calculate the ratio
class Device {
// Base width in point, use iPhone 6
static let base: CGFloat = 375
static var ratio: CGFloat {
return UIScreen.main.bounds.width / base
}
}
Extension to make it convenient
We can have a computed property called adjusted
that adjusts the size based on the ratio
extension CGFloat {
var adjusted: CGFloat {
return self * Device.ratio
}
}
extension Double {
var adjusted: CGFloat {
return CGFloat(self) * Device.ratio
}
}
extension Int {
var adjusted: CGFloat {
return CGFloat(self) * Device.ratio
}
}
Use the ratio
You can adjust as much as you want
label.font = UIFont.systemFont(ofSize: 23.adjusted)
phoneTextField.leftAnchor.constraint(equalTo: container.leftAnchor, constant: 30.adjusted),
phoneTextField.rightAnchor.constraint(equalTo: container.rightAnchor, constant: -30.adjusted),
imageView.widthAnchor.constraint(equalToConstant: 80.adjusted), imageView.heightAnchor.constraint(equalToConstant: 90.adjusted),
Hi I have a question.
Why is the height proportional to the width?
imageView.heightAnchor.constraint(equalToConstant: 90.adjusted)
use width adjusted