• Skip to main content
  • Skip to primary sidebar

Ravi Shankar

Tweaking Apps

  • Swift
  • Tech Tips

Auto Layout

Unable to simultaneously satisfy constraints.

October 17, 2019 By Ravi Shankar

A common error that we would see when using Auto Layout is

Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don’t want.

Debugging the verbose shown in the console might look difficult but if you closely go through the messages you should be able to identify the issue.

Let us take the following Auto Layout Constraint error messages.

Try this:
(1) look at each constraint and try to figure out which you don’t expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
“<NSLayoutConstraint:0x281862940 UIImageView:0x14ddb28e0.width == UIImageView:0x14ddb28e0.height (active)>”,
“<NSLayoutConstraint:0x28181c190 V:|-(5)-[UIImageView:0x14ddb28e0] (active, names: ‘|’:UITableViewCellContentView:0x14ddb2750 )>”,
“<NSLayoutConstraint:0x28181cc30 UIImageView:0x14ddb28e0.width == 0.22*UITableViewCellContentView:0x14ddb2750.width (active)>”,
“<NSLayoutConstraint:0x28181eb20 V:[UIImageView:0x14ddb28e0]-(5)-| (active, names: ‘|’:UITableViewCellContentView:0x14ddb2750 )>”,
“<NSLayoutConstraint:0x28186e080 ‘UIView-Encapsulated-Layout-Height’ UITableViewCellContentView:0x14ddb2750.height == 93 (active)>”,
“<NSLayoutConstraint:0x28186e030 ‘UIView-Encapsulated-Layout-Width’ UITableViewCellContentView:0x14ddb2750.width == 375 (active)>”
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x281862940 UIImageView:0x14ddb28e0.width == UIImageView:0x14ddb28e0.height (active)>

The constraints associated with this UIImageView are

This error is result of more than one constraints staistying the same condition. The last line in the log message tells one of the constraint causes this issues. “width == height”. Now identify the second constraint which tries to set the width of this imageview.

There are two constraints trying to set the width for the image view, 1. Propotional Width to and 2. Aspect Ratio. After removing the unwanted constraint and you are good to go.

Let us see one more example for the Constraint errors.

(
“<NSLayoutConstraint:0x281818f00 UIButton:0x14ddb7fe0’BOOK’.height == 50 (active)>”,
“<NSLayoutConstraint:0x28186c050 V:|-(20)-[UIButton:0x14ddb7fe0’BOOK’] (active, names: ‘|’:UITableViewCellContentView:0x14ddb7e50 )>”,
“<NSLayoutConstraint:0x28186c0a0 V:[UIButton:0x14ddb7fe0’BOOK’]-(20)-| (active, names: ‘|’:UITableViewCellContentView:0x14ddb7e50 )>”,
“<NSLayoutConstraint:0x28181aad0 ‘UIView-Encapsulated-Layout-Height’ UITableViewCellContentView:0x14ddb7e50.height == 90.5 (active)>”
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x281818f00 UIButton:0x14ddb7fe0’BOOK’.height == 50 (active)>

 

The last line gives a clue, there are two constraints trying to set the height of the BOOK button. And if you look at the constraints for the BOOK button, you can find 1. Top and Bottom constraints are set for button and 2. Height constraint is also set for Button. Removing any one of the constraint would fix the problem.

Filed Under: Auto Layout, Constraints, NSLayoutConstraint

Content Priority in Auto Layout

March 4, 2016 By Ravi Shankar 1 Comment

Auto Layout brings in lots of good features to ease the life of an iOS developer when designing User Interfaces. In this example, we will see how to use Content Priorities such as Content Hugging and Comrpession Resistance.

I have created a project with Single View Template and dispayed Size Classes as we are going to focus only on iPhone family.

Drag and drop two labels adjacent to each other.

Add Leading Space and Vertical Space constraints for Label A. Similarly add Vertical Space and Trailing Space constraints for Label B

 

Constraints for Label A

Constraints for Label B

Click the Update Frames option under the Resolve AutoLayout Issues menu. This should align the frames to reflect the constraints changes.

Change the background colour of Labels to Yellow and Green respectively. This would help us to identity the growth of each labels. Now add the Horizontal Spacing constraint between these two labels and set constant to 5.

Now Label B has grown and covered the space between both labels. Please note that this would be in random nature some times even Label A can fill up the space between these labels. And in this article, we will see how to control this behaviour. You will also notice the warning message that “2 views are horizontally ambitguous”. This is because Auto Layout does not know which label should grow and shrink in size.

Content Compression Resistance Priority

Let us change the text for Label in left hand side as “Content Hugging”. Simialrly enter the text for right hand side label as “Compression Resistance”. Then Update Frames to refelect the Intrinsic Content Size changes. You will notice that the Compression Resistance has a truncated trail.

If you want to this label to resist shrinking its size then set the Content Compression Resistance Priority (Under Size Inspector) to value higher than the label on left hand side.

After changing the value from 750 to 751, you will notice the warning messages “Frame will be different at run time”. Now Updating the Frames for All Views in Container shoud reflect as shown in the below screenshot.

Content Hugging Priority

Now Content Hugging label is partially hidden and it cannot grow horizontally as right hand side label has a higher compression resistance priority. Let us set the number of lines for this lable to 0 (which means it can grow based on the content size). This should again result in “Content Priority Ambiguity” error. This time we can fix this by telling Auto Layout that the label on left hand side has least resistance for growth. Select the label on left hand side, navigate to Size Inspector and set the Content Hugging Priority to lower than right hand side label i.e from 251 to 250.

Click Update Frames to resolve the warning message “Frame for Content Hugging will be different at run time”. The Content Hugging label in shown in two lines.

If you need any assistance in Auto Layout, check out our new iOS 9 Auto Layout Tutorials 50% Off.

Filed Under: Auto Layout, Xcode Tagged With: Compression Resistance, Content Hugging

How to programmatically add AutoLayout constraints?

February 18, 2016 By Ravi Shankar 2 Comments

AutoLayout solves the mystery when designing app for more than one screen size and for both Portrait and Landscape orientation. This is done by adding constraints to the views using various Auto Layout options available as part of Interface Builder. As an iOS developer, you can also add these constraints programmatically using NSLayoutConstraints or Visual Format Languages. In this tutorial we will see how to use NSLayoutConstraints for adding constraints to the views.

Screen Design For this Demo

For this demo, we will design something similar to flag of England by adding all the views and constraints programmatically. Funza Academy have published a video tutorial on how to design this screen using Interface Buidler, please check that out.

 

Overview of Steps

The following will be done to create the UI programmatically.

  1. Change the background colour of View to Red
  2. Add four rectangular views of equal widths on top left, top right, bottom left and bottom right of the parent view. The background colour for all these views will be set to red and Super View to red
  3. Pin the four rectangular views to the corresponding corner by adding constraints.
  4. Add constraints to the views to leave constant gap between each views (white background). This would ensure red line is shown in between these views.
  5. Disable AutoResizingMasks for teh four sub views.

Project Setup

Create a new Xcode project by selecting Single View Application for the project template. Also choose the language and Swift and iPhone for Devices.

Create Views

Navigate to ViewController.swift file and add the following code snippet after the class declaration and above the viewDidLoad() function.

[code language=”swift”]private let SCREEN_SIZE = UIScreen.mainScreen().bounds
private let GAP_BETWEEN_VIEWS:CGFloat = 0.08

// Create four Subviews

var topLeftView = UIView()
var topRightView = UIView()
var bottomLeftView = UIView()
var bottomRightView = UIView()[/code]

The above set of code creates two constants which stores the screen size and specifies the gap between the views. Then we have created four variables that holds the instance of four views.

Add the following addViews functions below the viewDidLoad method

[code language=”swift”]
func addViews() {
let heightOfSubView = SCREEN_SIZE.height / 2 – SCREEN_SIZE.height * GAP_BETWEEN_VIEWS/2
let widthOfSubView = SCREEN_SIZE.width / 2 – SCREEN_SIZE.height * GAP_BETWEEN_VIEWS/2

// Calculate the height and size of each views
topLeftView = UIView(frame: CGRect(x: 0, y: 0, width: widthOfSubView, height: heightOfSubView))
topRightView = UIView(frame: CGRect(x: widthOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), y: 0, width: widthOfSubView, height: heightOfSubView))
bottomLeftView = UIView(frame: CGRect(x: 0, y: heightOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), width: widthOfSubView, height: heightOfSubView))
bottomRightView = UIView(frame: CGRect(x: widthOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), y: heightOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), width: widthOfSubView, height: heightOfSubView))

topLeftView.backgroundColor = UIColor.whiteColor()
topRightView.backgroundColor = UIColor.whiteColor()
bottomLeftView.backgroundColor = UIColor.whiteColor()
bottomRightView.backgroundColor = UIColor.whiteColor()

view.addSubview(topLeftView)
view.addSubview(topRightView)
view.addSubview(bottomLeftView)
view.addSubview(bottomRightView)
}
[/code]

The addViews function, calculates the height and width of each subview (rectangular view with white background). Then the four views are created with positioning them in the corresponding corners i.e topLeft, topRight, bottomLeft and bottomRight. The background colour for these views are set White then they added to parent view using addSubView method.

Now call this addViews function inside viewDidLoad method. Also make sure to set the background colour of parent view to red.

[code language=”swift”]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.redColor()
addViews()
}
[/code]

Compiling and running this app on iPhone 6 simulator, the portrait mode should look as shown below

And in Landscape mode the views are randomly placed. Let us now fix this by adding the required constraints for all the veiws.

Add Constraints

In order to pin the four subviews, we need to add Leading, Traling, Top and Bottom constraints for the views based on their position. For example the top left view needs a leading and top constraint to the superview. The below screenshot should give a better understanding of constraints required for each view. And we will be adding these constraints using NSLayoutConstraint class

Pin the views to the side

Add the following code snippet that which creates Leading and Top constraint for TopLeft view.

[code language=”swift”]func addtopLeftViewConstraints() {
let topLeftViewLeadingConstraint = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)

let topLeftViewTopConstraint = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topLeftViewLeadingConstraint, topLeftViewTopConstraint])
}
[/code]

First we create a leading constraint to the topLeft view and super view. Then a top constraint is added for topLeft view to the SuperView. Constant refers to the gap between the views using attribute we specify the Leading or Top attributes. Since we do not need any gap between corners the constant value is set to 0. Finally we add these constraints for the view by using the activateConstraints function in NSLayoutConstraint class.

Now let us repeat the above steps topRight. bottomLeft and bottomLeft Views.

[code language=”swift”]func addTopRightViewConstraints() {

let topRightViewTrailingConstraint = NSLayoutConstraint(item: topRightView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)

let topRightViewTopConstraint = NSLayoutConstraint(item: topRightView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topRightViewTrailingConstraint, topRightViewTopConstraint])
}

func addBottomLeftViewConstraints() {

let bottomLeftViewLeadingConstraint = NSLayoutConstraint(item: bottomLeftView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)

let bottomLeftViewBottomConstraint = NSLayoutConstraint(item: bottomLeftView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([bottomLeftViewLeadingConstraint, bottomLeftViewBottomConstraint])

}

func addBottomRightViewConstraints() {

let bottomRightViewTrailingConstraint = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)

let bottomRightViewBottomConstraint = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([bottomRightViewTrailingConstraint, bottomRightViewBottomConstraint])
}[/code]

Leave space between views

We need leave constant space in the middle between these views. This can be achieved by adding constriants between the top/bottom views and left/right views. So basically we need to add two vertical spacing and two horizontal spacing constraints.

The below code snippet adds the required spacing constraings between views by specifying a constant value. Then activate these constraints by calling NSLayoutConstraint.activateConstraint.

[code language=”swift”] func addTopBottomConstraints() {
let verticalSpacing1 = NSLayoutConstraint(item: bottomLeftView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: topLeftView, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

let verticalSpacing2 = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: topRightView, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

NSLayoutConstraint.activateConstraints([verticalSpacing1, verticalSpacing2])
}

func addLeftRightConstraints() {
let horizontalSpacing1 = NSLayoutConstraint(item: topRightView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: topLeftView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

let horizontalSpacing2 = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: bottomLeftView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

NSLayoutConstraint.activateConstraints([horizontalSpacing1, horizontalSpacing2])
}
[/code]

Add Equal Width and Equal Height

Now add Equal Width and Equal Height constraints for topRight, bottomLeft and bottomRight views based on topLeft View. The code snippet for EqualWidth and EqualHeight is given below. The first function adds equal width constaints for all the three views based on TopLeft view. Similarly the second function adds equal height constraints based on the TopLeft view.

[code language=”swift”]
func addEqualWidthConstraints() {
let topRightViewWidth = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: topRightView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)

let bottomLeftViewWidth = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: bottomLeftView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)

let bottomRightViewWidth = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: bottomRightView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topRightViewWidth, bottomLeftViewWidth,bottomRightViewWidth ])
}

func addEqualHeightConstraints() {
let topRightViewHeight = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: topRightView, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0)

let bottomLeftViewHeight = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: bottomLeftView, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0)

let bottomRightViewHeight = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: bottomRightView, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topRightViewHeight, bottomLeftViewHeight,bottomRightViewHeight ])
}[/code]

Disable AutoResizingMasks

Finally we need to disable the auto resizing masks for all the views to prevent constraints getting automatically based on the autoResizingMask property. The autoResizingMask property is set to true when the views are added programmtically added so we need make sure that this property for all these views are set to false.

[code language=”swift”]func disableAutoResizingMasks() {
topLeftView.translatesAutoresizingMaskIntoConstraints = false
topRightView.translatesAutoresizingMaskIntoConstraints = false
bottomLeftView.translatesAutoresizingMaskIntoConstraints = false
bottomRightView.translatesAutoresizingMaskIntoConstraints = false
}[/code]

Just to make code little organized, we can create a new function that calls these constraints functions.

[code language=”swift”]func addConstraints() {
addtopLeftViewConstraints()
addTopRightViewConstraints()
addBottomLeftViewConstraints()
addBottomRightViewConstraints()
addTopBottomConstraints()
addLeftRightConstraints()
addEqualWidthConstraints()
addEqualHeightConstraints()
disableAutoResizingMasks()
}
[/code]

Then call the addConstraints function in viewDidLoad method

[code language=”swift”]override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = UIColor.redColor()

addViews()
addConstraints()
}[/code]

If you need any assistance in Auto Layout, check out our new iOS 9 Auto Layout Tutorials.

Download the source code from GitHub

Filed Under: Auto Layout, ios Tagged With: NSLayoutConstraint, Swift

Adaptive Layout in iOS

July 27, 2015 By Ravi Shankar

Adaptive Layout was introduced in iOS 8 to address the problem of designing user interface for different devices and screen sizes. In the earlier version of iOS, we had to maintain different storyboards for iPad and iPhone and with Adaptive Layout we just need one storyboard for all the devices. Some of the main components of Adpative Layout are Auto Layout, Size Classes and Trait Collections. Let us try to understand Adpative Layout by designing the following User Interface for various devices and screen sizes.

Create an universal project choosing Single View Application template. You can download the project from GitHub to get the images used in this demo and add them to Images.xcassets.

iPhone (Portrait)

Make sure you have selected the size classes as wAny hAny in the Storyboard.

Add a UIImageView, button and 2 labels then provide necessary details as shown below.

First let us design the screen for iPhones in Portrait mode by keeping Preview (Assistant Editor) adjacent to Interface builder.

Select the iPhone 6 caption label, align it centre horizontally to the container by using the Align option.

Set the distance from top layout to the label as 5 using the Pin option.

Now select the imageview and align it centre horizontally and Vertically to the container by using the Align option.

The specify the width and height constraint for the imageview using the Pin option. This would ensure that the size of imageview is uniform in all the devices.

Now select the Buy Now button and add contraints to the trailing and bottom of the button. Control + drag from button to View and select Trailing space to container margin.

Repeat Control + drag from button to the bottom of the View and select Bottom Space to Bottom Layout Guide.

Then using the Pin option add width and height constraints for the button.

Finally the select the label which is used for displaying the price and Control + drag from label to the container.

Edit the Trailing Space constraint for Price label with Buy Now button and set it to 5.

Previewing the screen changes for iPhone 3.5 and iPhone 4 should look as shown below

iPad (Portrait & Landscape)

iPad has lots of screen space compared to an iPhone. Let us to see how to maximize the screen usage of an iPad by adding an extra image.

Set the size classes to wRegular hRegular to design user interfaces for iPad and iPhone. The imageview is currently aligned to centre both horizontally and vertically. We need to remove the horizontal constraint (Center X) so that the imageview can be moved towards the left handside. This should create an extra space to add another imageview to the View Controller.

Disable the Center X constraint for iPhone by navigating to Size Inspector and press the delete key.

Then pin the imageview to left side of the view without setting any margin (Pin option).

Use the Update Frame option under Resolve Auto Layout Issues to move the views based on the applied constraints. Add another ImageView to View Controller then select an iPhone 6 black image and set the view mode to Aspect Fit.

Control + drag from the imageview on the right hand side to imageview on the left hand side. Select Center Y from the list of available constraints.

Changing Font Size for Size Classes

Adaptive Layout allows you to specify different font size based on the size class. In the Show Attributes Inspector, click the + sign next Font option and choose wRegularWidth hRegularHeight option. Now you can customize the font properties specific to iPad

Now you should see the extra image just for iPads in portrait and Landscape mode. Still there are lots of empty space but you can fill them as part of your code challenege :-). May be you can other details such as add description, rating button etc..

When you navigate back to wAny hAny size classes, the document outline should show the new image as greyed out. As the second imageview is available only in regular size classes. Also the attributes inspector for the second imageview should provide the details on installed size classes.

The above screenshot shows that the control installed only in wR wH size classes and not wAny hAny size classes.

iPhone (Landscape)

When previewing the design in both portrait and landscape, you must have noticed that some controls are hidden in landscape mode. This can be fixed by making necessary changes to compact size classes.

Set the size classes to wAny hCompact in the storyboard. Select the imageview, navigate to Size Inspector and disable the Center X constraint.

Adjust the size of imageview if it is too large in landscape mode. To reflect frame changes, select Update Constraint under Resolve Auto Layout Issues option. Another way is by editing the width and height constraint for the imageview.

Since we want to move the price lable above the Buy Now button, remove all the constraints associated with the label.

Move the label just above the Buy Now button and centre align to the imageview.

Control + drag from Price label to Buy Now button and select Center X constraint.

Repeat the above step but this time from Price label to ImageView and select Center Y Constraint.

The final preview of screen in iPhone 3.5 portrait and landscape mode should look as shown below.

Download the source code from here

Summary

We have covered some basics of Adaptive Layout by designing user interface with size classes. changing font attibutes, installing controls,disable and editing constraints based on different size classes.

Filed Under: Adaptive Layout, Auto Layout, Size Classes

Auto Layout in iOS

July 25, 2015 By Ravi Shankar 5 Comments

Using Auto Layout feature developers can align UI controls for different devices, screen sizes and orientation. This reduces the code to be maintained and makes life easy for the developers. Auto Layout solves UI design issues by creating relationship between the UI elements. This follows constraint based layout system where you can define contraints for each UI elements. Let us see some basics of Auto Layout by looking at four different scenarios

The objective of this article is to provide details on the following

  • Different ways to add constraints to UI elements.
  • How to centre align a control to both vertically and horizantally to container.
  • Arrange three controls in single column with centre aligned horizontally to the container.
  • Design simple login form by embeding the controls inside view
  • Design a form where the width of controls gets adjusted based on device orientation.
  • Clear and Edit constraints.
  • Pinning constraint and Updating frames

Center Align image Vertical and Horizontal to the container

For this demo, let us start with a single view application project. Drag and drop an UIImageView from object libary on to View Controller. Copy an image to your project and set that image to UIImageView using Attributes Inspector (Download the image from GitHub project).

You might be familiar with Size Inspector under Xcode’s Utilies Pane. This helps us to enter the height, width, x and y position for any UI elements.

Another alternate way to enter the size and postion for elements by adding constraints using the Auto Layout option which is available at the bottom of the Interface builder.

Select the Click the Pin option, enter value for Width and Height as 300 then Add these 2 Constraints.

After applying the constraint, you should notice orange dashed line indicating that your control is out of position. Let us update the frame afer applying all the required constraints.

Click Align option (first option) and select Horizontal and Vertical Center in Container then Add these 2 Constraints.

If the ImageView on the ViewController is in misplaced position, the document outline will show an yellow color indication mark at top right hand corner. You can select that icon to find more details about the issue.

Document Outline

Document Outline in the Storyboard lists down the installed controls for a scene. Also you can the list of constraints added for these controls. If you do not need any constraint then you select it and delete them in Document Outline.

The missplaced views can be fixed by selecting Update Frames option under Resolve Auto Layout Issues (Auto Layout option with a triangle).

Preview User Interface changes

Now you can preview user interface changes on various device by using the Preview option. Click the icon for showing Assistant Editor window. Navigate to Preview and select Main.storyboard option as shown in the below screenshot.

You can use + sign to preview the screen in a specific device and also use rotate screen option to preview the changes in different screen orientation.

Arrange three Buttons in single column

In the next demo, we wil try to arrange three buttons aligned horizontally center to View and in a single column. Add a View Controller to the storyboard then drag drop three buttons on the View Controller. Though we have used the guidelines to align these buttons they don’t look the same when you preview them.

Now let us see how to fix these UI issues by adding constraints.

First select the Button with caption as Auto Layout 2 and make it Horizontal and Vertical Center in Container then Add these two constraints. This would make sure the Auto Layout 2 button is aligned center to the View both vertically and horizontally.

Select the button with caption as Auto Layout 1. Use the Aign option and add Horizontal Center in Container constraint.

Now you need to specify the Centre X and Verical Spacing constraint for this button. This can be done by control dragging from Auto Layout 1 button to Auto Layout 2 and you will be presented with the following option.

Select Vertical Spacing to position the control at constant distance from Auto Layout 2. Repeat the same control drag from Auto Layout 1 and Auto Layout 2 and this time choose Centre X.

Now repeat the above steps for Auto Layout 3 with Auto Layout 2 i.e add Centre X and Vertical Spacing constraints.

 

Scenario 3:- Adjust control width based on screen orientation

This scenario explains how to add constraints so that controls width increases or decreases based on the screen size. For example in the below screenshots, the width for textfields provided for entering name and Age gets adjusted based on screen orientation

Add a new View Controller on to Storyboard then add 2 labels and 2 textfields and a button. Provide the caption for both labels as Name, Age and Submit (button) respectively. We need to add constraints to labels so that their width and position are fixed at the specified location. And for both the textfields, constraints have to be added to trailing edge so that width increases or decreases based on the orientation

Add three constraints to the label with caption as Name using the pin option as shown in the below screenshot.

Repeat the same for label with caption as Age

Select the textfield adjacent to Name label, control drag from textfield to the container then select Trailing Space to Container Margin.

Need to align the textfield with the label, control drag from text field to name label and select Centre Y from the list of constraints.

Keeping the textField selected, navigate to Size Inspector (Utilities Pane) and cick Edit on Trailing Space constraint. Set the value for the constant as 10 as we want to maintain the space between textfield and container to 10 in both landscape and portrait mode.

Repeat the above steps done for Age textfields as well.

Finally we need to add two constraints for the Submit button to make sure it is aligned on the right hand side at certain distance from the Top Layout. Control drag from button to top of the container and select Top Space to Top Layout Guide.

Again repeat the above step by this time to side of the container and select Trailing Space to Container Margin.

Now prevewing the screen in Portait and Landscape mode should look as shown below.

Scenario 4:- Apply constraints to Embedded View

In this demo, let us see how to embed controls within a view and apply constraints to the embedded View instead of applying to the individual constraints.

Note :- Button has been incorrect named as Password it needs to be Register. The source code has been updated with this name change.

Add 2 textfields, 2 buttons and provide name and placeholder text as shown below.

Select these controls and embed them inside a View by navigating to Editor menu -> Embed -> View

Now change the background colour of the View and buttons to dark gray and orange.

Select the Embedded View, click Align option and make the View centre align to both Horizontal and Vertical to the Container.

Also add the width and height constraints for the Embedded View keeping the current value.

Now you might see a dashed orange colour line indicating the view is in misplaced position. You can fix this by selecting Update Frame under Resolve Auto Layout Issues option. Please make sure to select Update Frame option under Selected Views and not the container

Previewing the screen in both portrait and landscape should look as shown below

We have seen an introduction to Auto Layout using Storyboard. You can also add constraints via code using NSLayoutConstraint API or Visual Formatting language.

If you need any assistance in Auto Layout, check out our new iOS 9 Auto Layout Tutorials.

Download the source from GitHub

Filed Under: Auto Layout, Programming, Xcode

Primary Sidebar

TwitterLinkedin

Recent Posts

  • How to block keywords in Jio broadband
  • How to disable opening an app automatically at login in Mac
  • How to set preferred Wifi network on Mac
  • Attribute Unavailable: Estimated section warning before iOS 11.0
  • How to recover Firefox password from Time Machine backup

Pages

  • About
  • Privacy Policy
  • Terms and Conditions

Copyright 2022 © rshankar.com

Terms and Conditions - Privacy Policy