Adaptive layout programmatically in Swift

This article is based on my previous one, so before moving on, I’d recommend you to read it first:

Note

I’ll be using SnapKit in my code, but the approach can be applied to other layout libraries as well as Apple’s NSLayoutConstraint and SwiftUI.

How to adapt constants

To tackle this problem, we’ll use the adapted function (the implementation is explained in the article above) and Int extension.

In a nutshell, the adapted function allows us to adapt constant dynamically depending on device screen dimensions.

IntExtension (line 11–19)

This Int extension contains 2 computed properties:

  • VAdapted (Vertically Adapted) — this computed property adapts constant relative to the vertical plane
  • HAdapted (Horizontally Adapted) — this computed property adapts constant relative to the horizontal plane

Here is the usage example:

In the code snippet above, we constraint a view to the top and left. And since we’ve provided adapted constants using VAdapted and HAdapted computed properties, the constants will vary on different screen sizes.

I want to stress that the constants will be adapted based on initially provided ones relative to the base screen size

This means if you choose iPhone 8 as your base device and call 100.VAdapted, the following steps will be taken:

  1. The ratio will be calculated:
    100 / 667 ≈ 0.15, where
    100 — constant
    667 — base screen height
  2. This ratio will be used to modify the constant for other screen dimensions. For example, let’s imagine that we’ve opened the app on iPhone 12 Pro Max. The following calculation will take place:
    926 × 0.15 ≈ 140, where
    926 — target device screen height
    0.15 — the ratio obtained in the first step
  3. The result will be returned

The above steps show us that the initial ratio is calculated based on the base device and will be kept regardless of the size of other devices.

How to resize view proportionally

To resize the view proportionally, we’ll use the resized function (you can find the implementation in my article above) and Array extension.

In short, the resized function allows us to resize the view proportionally preserving the initial aspect ratio.

ArrayExtension (line 11–21)

To make the usage as simple as possible, I’ve decided to create an Array extension and limit the access to additional functionality only for arrays of type Int.

The extension contains 2 computed properties:

  • VResized (Vertically Resized) — this computed property resizes constants relative to the vertical plane
  • HResized (Horizontally Resized) — this computed property resizes constants relative to the horizontal plane

These properties resize constants based on the Int array, where the first value represents the width and the second value represents the height.

In order to prevent incorrect use of the properties, there is a guard statement, which throws fatalError if the array count more or less than 2 elements.

The usage is as simple as that:

Under the hood the following steps will be taken:

  1. The aspect ratio will be calculated:
    60 / 250 = 0.24, where
    60 — view height for the base device
    250 — view width for the base device
  2. New width will be calculated first since HResized property was chosen:
    428 × (250 / 375) ≈ 285, where
    428— target device screen width
    250 — view width
    375— base screen width
  3. New height will be calculated based on a new width and aspect ratio obtained in the first step:
    285 × 0.24 ≈ 68, where
    285 — new view width
    0.24 — aspect ratio
  4. The result will be returned:
    CGSize(width: 285, height: 68)

I want to note that there is a rule according to which you have to opt for either VResized or HResized:

If the width is greater than the height, you should choose HResized, respectively if the height is greater than the width, you should choose VResized. If the width and the height are equal, you should choose HResized.

Result

Here you can see the sample layout, which was created using the approach described in the article:

Conclusion

The benefit of this approach is that it allows us to layout our screens using the dimensions specified in the design, and be sure that they’ll be adapted to all screen sizes automatically.

Source code

The source code and real usage example can be found in my GitHub repository:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store