Using aspect ratio with Auto Layout in iOS

Subscribe to my newsletter and never miss my upcoming articles

Hello friends, Leo here.

Today we'll quickly explore a problema with images and layouts. Aspect ratio is an important feature to master because nowadays we have a bunch of screen sizes, this implies on layout changing regarding the width and the height of the screen. If you want your views have always the same aspect ratio without having to concern the screen size, this post is for you!

It's said that the old artists used the golden ratio to paint their pieces. Can you spot on the image of this post where Rembrandt used this?

Let's code!

Problem

Your backend will send you images with size with 344 width and 200 height. You want to your UITableViewCell fit this proportion.

First we have to do is to think what dimension we will anchor on. To this problem we will anchor on the width of the screen. So we can use some math to calculate the aspect ratio of the image, and with that we can set the height anchor of the cell.

Math

To calculate the aspect ratio you just make a division based in X/Y where X is the dimension we want to make adaptable and the Y is the anchor dimension. On problem set above we will use the width as the anchor because the design team said that the width of the view will have constant padding of each side. So if you think that width can change, the height of the image must proportionally change too.

The math will seem 344/200 and gave us 0.5813 as answer. So now we know that no matter what auto calculated size of the width, the height will be 0.58 times that. And with this info we can code the auto layout for the view.

Auto Layout

Open your playgrounds and you can paste this code there.

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController, UITableViewDataSource, UITableViewDelegate {

    let dataArray = [("Title","Subtitle 2131 "),("Title","Subtitle 2131"),("Title","Subtitle 2131")]
    let tableview = UITableView()

    override func loadView() {
        let view = UIView()
        self.view = view
    }

    override func viewDidLoad() {
        view.addSubview(tableview)

        tableview.translatesAutoresizingMaskIntoConstraints = false
        tableview.dataSource = self
        tableview.delegate = self
        tableview.register(VariantsTableViewCell.self, forCellReuseIdentifier: VariantsTableViewCell.cellID)
        tableview.separatorStyle = .none
        NSLayoutConstraint.activate([
            tableview.topAnchor.constraint(equalTo: view.topAnchor),
            tableview.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            tableview.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableview.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableview.dequeueReusableCell(withIdentifier: VariantsTableViewCell.cellID) as! VariantsTableViewCell        
        return cell
    }
}

PlaygroundPage.current.liveView = MyViewController()

And the this will basically configure a table view. Now we will implement the aspect ratio on the cell view:

class VariantsTableViewCell: UITableViewCell {

    static let cellID = "cell"
    private var backgroundImage: UIImageView!

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        configureCellView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func configureCellView() {
        configureBackgroundImageView()
    }

    private func configureBackgroundImageView() {

        backgroundImage = UIImageView()
        backgroundImage.backgroundColor = .red
        backgroundImage.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(backgroundImage)

        NSLayoutConstraint.activate([
            backgroundImage.leadingAnchor.constraint(equalTo:
                     contentView.leadingAnchor, constant: 10),
            backgroundImage.trailingAnchor.constraint(equalTo:
                      contentView.trailingAnchor, constant: -10),
            backgroundImage.topAnchor.constraint(equalTo:
                     contentView.topAnchor, constant: 5),
            backgroundImage.bottomAnchor.constraint(equalTo:
                    contentView.bottomAnchor, constant: -10),
            backgroundImage.heightAnchor.constraint(equalTo:
                   backgroundImage.widthAnchor, multiplier: 0.58) // this line do the aspect ratio
        ])
    }
}

As you can see the last line on NSLayoutConstraint.activate func are setting the height of the UITableViewCell to be 0.58 times the width. This way you can always assure that images with this aspect ratio will fit perfectly on your layout in iOS. The result should be the image below:

Screen Shot 2021-01-28 at 08.58.15.png

Conclusion

This was a brief explanation on how important is to understand the aspect ratio using auto layout and I hope you enjoy the reading. Any feedbacks or comments are welcome.

Thanks for reading and... That's all folks.

Credits: image

No Comments Yet