Building Adaptive Layout with Size Classes — Programmatically
Photo by Etienne Boulanger on Unsplash

Building Adaptive Layout with Size Classes — Programmatically

Previously, building the user interface for iOS was very simply because there was only one iPhone size. The time has passed, we now have an array of iPhone sizes with the different screen sizes and orientations.

Imagine a layout being displayed on a screen with different dimensions.

How can you make these sorts of adjustments to a layout?

To do them the way you want, you must develop a separate condition and control mechanism for each view element.

Apple has introduced(in iOS 8) Size Classes which organize all of these screen sizes for each device and orientation into two categories.

To simplify, Apple proposes a new paradigm. Instead of evaluating your layout in terms of many device types, resolution, multitasking mode, and device orientation, you should focus on setting your layout to two widths (called compact and regular) and two height types (also compact and regular). These distinctions are called dimension classes. You can then use these dimension classes to define or adjust your layout.

Size classes decrease all different potential horizontal and vertical configurations to only compact and regular types: compact for more limited space; and regular for less limited space.

See figure 1 how the size classes correspond to devices and device orientations.

Different size class combinations apply to the full-screen experience on different devices, based on screen size.

Figure 1. Size Classes for iPhone

Working With Size Classes

In this guide, I am going to assist you with programmatically. I can’t wait to move the main.storyboard to the trash when creating a project. This is a hobby for me.

Let’s start by setting up the basic interface and constraints.

Now I’m going to create two images and sequence them with auto layout. Then, I will make sure that these two images are suitable for the orientation of different iPhone devices.

Create three different arrays, that contains NSLayoutConstraint type. That should be like below. We will store the constraints according to device orientations.

private var compactConstraints: [NSLayoutConstraint] = []
private var regularConstraints: [NSLayoutConstraint] = []
private var sharedConstraints: [NSLayoutConstraint] = []

And then create UI elements. You will see that it contains three elements; viewContainer, image1 and image2.

private lazy var viewContainer: UIView = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

private lazy var image1: UIImageView = {
    let image1 = UIImageView()
    image1.translatesAutoresizingMaskIntoConstraints = false
    image1.image = UIImage(named: "apple")
    image1.contentMode = .scaleAspectFit
    return image1
}()

private lazy var image2: UIImageView = {
    let image2 = UIImageView()
    image2.translatesAutoresizingMaskIntoConstraints = false
    image2.image = UIImage(named: "swift")
    image2.contentMode = .scaleAspectFit
    return image2
}()

Create a function named setupUI. setupUI is gathered up all views and adds them to super view.

func setupUI() {
    view.addSubview(viewContainer)
    viewContainer.addSubview(image1)
    viewContainer.addSubview(image2)
}

After that, you should create the second function like below. This function includes three arrays of constraints.

  1. sharedConstraints, the array holds common constraints for all various.
  2. regularConstraints, the array holds regular varying.
  3. compactConstraints, the array hold compact varying.
func setupConstraints() {
    sharedConstraints.append(contentsOf: [
        viewContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
        viewContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -15),
        viewContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15),
        viewContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 15),

        image1.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        image1.topAnchor.constraint(equalTo: view.topAnchor),
        image2.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        image2.trailingAnchor.constraint(equalTo: view.trailingAnchor),

    ])

    regularConstraints.append(contentsOf: [
        image1.trailingAnchor.constraint(equalTo: image2.leadingAnchor, constant: -10),
        image1.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        image2.topAnchor.constraint(equalTo: view.topAnchor),
    ])

    compactConstraints.append(contentsOf: [
        image1.bottomAnchor.constraint(equalTo: image2.topAnchor, constant: -10),
        image1.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        image2.leadingAnchor.constraint(equalTo: view.leadingAnchor)
    ])
}

We came to the most important part. This method decisions for auto layout with selected iPhone screen size and orientations. By sending the trait collection parameter and that determines the size classes

func layoutTrait(traitCollection:UITraitCollection) {
    if (!sharedConstraints[0].isActive) {
       // activating shared constraints
       NSLayoutConstraint.activate(sharedConstraints)
    }
    if traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular {
        if regularConstraints.count > 0 && regularConstraints[0].isActive {
            NSLayoutConstraint.deactivate(regularConstraints)
        }
        // activating compact constraints
        NSLayoutConstraint.activate(compactConstraints)
    } else {
        if compactConstraints.count > 0 && compactConstraints[0].isActive {
            NSLayoutConstraint.deactivate(compactConstraints)
        }
        // activating regular constraints
        NSLayoutConstraint.activate(regularConstraints)
    }
}

Override traitCollectionDidChange method, this will be notified when iPhone has changed in different orientations.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {

    super.traitCollectionDidChange(previousTraitCollection)

    layoutTrait(traitCollection: traitCollection)
}


And final step. In viewDidLoad method you should call these functions.

  1. setupUI is preparing the UI.
  2. setupConsraints are preparing the all auto layout constraints.
  3. And then activate common constraints
  4. The last row captures the current traitCollection and sends it to the layoutTrait method.


override func viewDidLoad() {
    super.viewDidLoad()

    setupUI()
    setupConstraints()

    NSLayoutConstraint.activate(sharedConstraints)
    layoutTrait(traitCollection: UIScreen.main.traitCollection)
}


You’re done varying the layout!.

Understanding Size Classes allows you the flexibility to development for different screen size. Size class traits make possible to support multiple devices and orientations.

For More information check out the Apple Link


If you have any criticism, question, or suggestion, feel free to post them in the comment section below!

Thanks for reading.

If you find this article worth sharing, please share it with your friends.


要查看或添加评论,请登录

Bat?kan SOSUN的更多文章

社区洞察

其他会员也浏览了