Auto Layout with Visual Format Language

Using Visual Format Language, with a single line of code, you can specify multiple constraints in either the horizontal or vertical direction.

Available Symbols in VFL:

  • | superview
  • - standard spacing (usually 8 points; value can be changed if it is the spacing to the edge of a superview)
  • == equal widths
  • -10- non standard spacing (10 points)
  • <= less than or equal to
  • >= greater than or equal to
  • @250 priority of the constraint, can have any value between 0 and 1000.

Visual Format Syntax:-

  • H: Indicates horizontal orientation.
  • V: Indicates vertical orientation.
  • If you’re not mentioning H:/V:, Auto Layout defaults to horizontal orientation.
  • Spacing — it defines space between the two views. If you provided space value explicitly, Autolayout takes that value to define space between views else default spacing 8 will be added.
  • View with default spacing can be represented as: [view1]-[view2]
  • View with custom spacing can be represented as: [view1]-10-[view2]
  • View without spacing can be represented as: [view1][view2]
  • [View] — View that laying out required
  • Width Constraint: used for adding width to view. You need to provide width of views into horizontal constraints.
  • Width of view with greater than or equal to constant can be represented as: [View(>=constant)] .e.g View width ≥50 is represented as: [View(>=50)]
  • Width of view with less than or equal to constant can be represented as: [View(<=constant)]. e.g: View width ≥50 is represented as: [View(<=50)]
  • Width of view equal to constant can be represented as: [View(constant)]. e.g: View width = 50 is represented as: [View(50)]
  • Height Constraint: used for adding height to view. You need to provide Height of views into vertical constraints.
  • Height of view with greater than or equal to constant can be represented as: V:|[View(>=constant)] .e.g View height ≥50 is represented as: V:|[View(>=50)]
  • Connection to Superview(|) : Used for connecting view with superview
  • Connecting view to superview with default spacing as: |-[view]-|
  • Connecting view to superview with custom spacing as: |-constant-[view]-constant-|. e.g: |-50-[button]-50-|
  • Priority : Can be set as [view(widthValue@priorityvalue)]. e.g: [view(50@250)]
  • Equal Widths : equal width of two views can be represented as [View1(==View2)]
  • Multiple Predicates: multiple predicates of view can be represented as [view1(>=constant,<=constant)]. e.g: [view1(>=70,<=100)]

Some example of VFL and respective view image:-

1. VFL and 2: View layout look
1. VFL and 2: Two views layout vertically with spacing 10
1. VFL and 2: View layout look

Refer apple doc for more example

Example Format String:

  • Consider a view which contains label with size 50, button with size 150 and flexible textfield, which are horizontally oriented. Spacing between each views are 10. Spacing between label and superview is 8. spacing between textfield and superview is 8. Visual format look like this for horizontal layout
H:|-[label(50)]-10-[button(150)]-10-[textField(>=100)]-|
  • Consider a view which contains button with size 150 and View with size 50, which are vertically oriented. Spacing between each views are 10. Visual format look like this for vertical layout
V:[button(50)]-10-[View(50)

Creating Constraints

Apple provides the class method constraints(withVisualFormat:options:metrics:views:) on NSLayoutConstraint to create constraints.

let views: [String: Any] = [
"label": label,
"button": button,
"textfield": textfield,
"view": view
]
let horizontalConstraints= NSLayoutConstraint.constraints(
withVisualFormat: "H:|-[label(50)]-10-[button(150)]-10-[textField(>=100)]-|",
metrics: nil,
views: views)
let verticalConstraints = NSLayoutConstraint.constraints(
withVisualFormat: "V:[button]-10-[View(50)",
metrics: nil,
views: views)
NSLayoutConstraint.activate(horizontalConstraints)NSLayoutConstraint.activate(verticalConstraints)

Metrics:

Metrics are a dictionary of number values that can appear inside the VFL format string. These are particularly useful if you have standardized spacing or calculated size values that you can’t type directly into the format string.

private enum Metrics {
static let padding: CGFloat = 10
}
let metrics = [
"horizontalPadding": Metrics.padding
]
let horizontal= NSLayoutConstraint.constraints(
withVisualFormat: "H:|-[label(50)]-horizontalPadding-[button(150)]-horizontalPadding-[textField(>=100)]-|",
metrics: metrics,
views: views)

use view.safeAreaInsets to calculate safe area

Layout Options:

Layout options provide the ability to manipulate view constraints perpendicular to the current layout orientation being defined.

E.g: — Apply vertical centering to all views in a horizontal layout orientation by using NSLayoutFormatOptions.AlignAllCenterY

NSLayoutConstraint.constraints(
withVisualFormat: "H:|-[label(50)]-horizontalPadding-[button(150)]-horizontalPadding-[textField(>=100)]-|",
options: [.alignAllCenterY],
metrics: nil,
views: views)

Demo:-

  • Create a Red view and add that as a subview

let
redView = UIView()
redView.backgroundColor = .redredView.translatesAutoresizingMaskIntoConstraints = falseview.addSubview(redView)let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[redView]|", options: .directionLeftToRight, metrics: nil, views: ["redView": redView])let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[redView]|", options: .alignAllTop, metrics: nil, views: ["redView": redView])NSLayoutConstraint.activate(horizontalConstraints)NSLayoutConstraint.activate(verticalConstraints)
  • Create red and Green View with equal width and full screen height as follows
let redView = UIView()redView.backgroundColor = .redredView.translatesAutoresizingMaskIntoConstraints  = falseview.addSubview(redView)let greenView = UIView()greenView.backgroundColor = .greengreenView.translatesAutoresizingMaskIntoConstraints  = falseview.addSubview(greenView)let views = ["redView": redView, "greenView": greenView]let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[redView(>=100,<=200@20)]-0-[greenView(==redView)]|", options: .directionLeftToRight, metrics: nil, views: views)let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[redView]|", options: .alignAllTop, metrics: nil, views: views)let verticalConstraintsForGreen = NSLayoutConstraint.constraints(withVisualFormat: "V:|[greenView]|", options: .alignAllTop, metrics: nil, views: views)NSLayoutConstraint.activate(horizontalConstraints)NSLayoutConstraint.activate(verticalConstraints)NSLayoutConstraint.activate(verticalConstraintsForGreen)
  • Create a redview with (x = 50, y = 50, width = screenSize-100, height = 100)

let
redView = UIView()
redView.backgroundColor = .redredView.translatesAutoresizingMaskIntoConstraints = falseview.addSubview(redView)let views = ["redView": redView]let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-50-[redView]-50-|", options: .directionLeftToRight, metrics: nil, views: views)let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-50-[redView(100)]", options: .alignAllTop, metrics: nil, views: views)NSLayoutConstraint.activate(horizontalConstraints)NSLayoutConstraint.activate(verticalConstraints)

I hope you find this blog helpful. If you enjoyed it, feel free to hit the clap button below 👏 to help others find it! and follow me on Medium. Thanks for reading ❤❤❤❤.

--

--

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