How to create percentage of total width using autolayout?

Solution 1:

If, as you say, you know how to do it in code, then you already know how to do it in the storyboard. It's exactly the same constraints, but you are creating them visually rather than in code.

  1. Select both a view and its superview.

  2. Choose Editor -> Pin -> Widths Equally to constrain the width to be equal to the superview's width (actually the "pin" popup dialog at the bottom of the canvas works best here).

  3. Edit the constraint and set the Multiplier to the desired fraction, e.g. 0.42. And so too for the other views.

Solution 2:

As Apple introduces UIStackView it made job much easy.

Method 1: Using Nib/StoryBoard:

You have to just add three view in interface builder & embed them into stackview

Xcode ► Editor ► Embed in ► StackView

enter image description here

Select stackView & give constraint with leading, trailing, top & equal height with safeArea

Click to Attribute inspector area & Set StackView horizontal & distribution to fill proportionally

[enter image description here3

Give constraint of three view with leading, trailing, top, bottom with respective of sides. enter image description here

Method 2: Programmatically:

import UIKit
class StackViewProgramatically: UIViewController {
    var propotionalStackView: UIStackView!
    ///Initially defining three views
    let redView: UIView = {
        let view = UIView()//taking 42 % initially
        view.frame = CGRect(x: 0, y: 0, width: 42 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .red
        return view
    }()

    let greenView: UIView = {
        let view = UIView()//taking 42* initially
        view.frame = CGRect(x: 42 * UIScreen.main.bounds.width/100, y: 0, width: 25 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .green
        return view
    }()
    let blueView: UIView = {
        let view = UIView()//taking 33*initially
        view.frame = CGRect(x: 67 * UIScreen.main.bounds.width/100, y: 0, width: 33 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .blue
        return view
    }()

    ///Changing UIView frame to supports landscape mode.
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        DispatchQueue.main.async {
            self.redView.frame = CGRect(x: 0, y: 0, width: 42 * self.widthPercent, height: self.screenHeight)
            self.greenView.frame = CGRect(x: 42 * self.widthPercent, y: 0, width: 25 * self.widthPercent, height: self.screenHeight)
            self.blueView.frame = CGRect(x: 67 * self.widthPercent, y: 0, width: 33 * self.widthPercent, height: self.screenHeight)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        //Adding subViews to the stackView
        propotionalStackView = UIStackView()
        propotionalStackView.addSubview(redView)
        propotionalStackView.addSubview(greenView)
        propotionalStackView.addSubview(blueView)
        propotionalStackView.spacing = 0
        ///setting up stackView
        propotionalStackView.axis = .horizontal
        propotionalStackView.distribution = .fillProportionally
        propotionalStackView.alignment = .fill
        view.addSubview(propotionalStackView)
    }
}
//MARK: UIscreen helper extension
extension NSObject {

    var widthPercent: CGFloat {
        return UIScreen.main.bounds.width/100
    }

    var screenHeight: CGFloat {
        return UIScreen.main.bounds.height
    }
}

Output:

Works with landscape & portrait

enter image description here enter image description here

Demo project - https://github.com/janeshsutharios/UIStackView-with-constraints

https://developer.apple.com/videos/play/wwdc2015/218/

Solution 3:

I think this can be explained in more detail so it can be more easily applied to any number of views requiring fixed percentage layouts within a superview.

Left-most view

  • Anchored to SuperView.Leading
  • Defines its fixed percentage as a multiplier on the SuperView.Height

Intermediate views

  • Defines its fixed percentage as a multiplier on the SuperView.Height
  • Pins its left to its neighbor's right

Right-Most view

  • Does not define a fixed percentage (it is the remainder of the available view)
  • Pins its left to its neighbor's right
  • Pins its right to SuperView.Trailing

All Views

  • Define their non-fixed heights by anchoring to Top Layout Guide.Top and Top Layout Guide.bottom. In the answer above, it is noted that this can also be done by setting equal height to the neighboring view.